/*
 * libExtended2.c
 *
 *  Created on: 16/04/2012
 *      Author: utnso
 */

#include "libExtended2.h"

static staticGroupDescriptor_t* staticGroupDescriptorTable = NULL;
static groupDescriptor_t* groupDescriptorTableAux = NULL;
static pthread_rwlock_t rwlockGroupDescriptorTable = PTHREAD_RWLOCK_INITIALIZER;
static staticSuperBlock_t staticSuperBlock = { 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static nodoFileList_t *fileList = NULL;
static pthread_mutex_t mutexFileList = PTHREAD_MUTEX_INITIALIZER;

int8_t inicializarFileSystem() {
	leerSuperBlock();
	groupDescriptor_t* groupDescriptor = leerGroupDescriptorTable();
	free(groupDescriptor);
	return 0;
}
//--------------------------------------------------
//LECTURA Y ESCRITURA DE BLOQUES
//--------------------------------------------------

char* leerBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock) {
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, numBlock);
	return leerBloqueGlobal(numBloqueGlobal);
}

char* leerBloqueGlobal(uint32_t numBlock) {
	printfCUCA("Tengo que leer completamente el bloque %d.\n", numBlock);
	//printfCUCA("Tengo que leer el bloque [%d].\n", (uint32_t) numBlock);
	char* contenido;
	char* key = obtenerKeyBloque(numBlock);
	size_t valueSize;
	uint32_t flags;
	memcached_return_t errorCache;
	contenido = obtenerDatoDeCache(key, strlen(key), &valueSize, &flags, &errorCache);
	if (contenido == NULL) {
		//el dato no estaba en la cache, lo leo del disco y lo guardo en la cache
		contenido = leerBytes((off_t) numBlock * staticSuperBlock.blockSize, (size_t) staticSuperBlock.blockSize);
		errorCache = almacenarDatoEnCache(key, strlen(key), contenido, (size_t) staticSuperBlock.blockSize, 0, 0);
	}
	free(key);
	//printfCUCA("Su contenido es:\n");
	//uint16_t i;
	//for(i = 0; i < staticSuperBlock.blockSize; i++){
	//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, contenido[i], contenido[i]);
	//}
	return contenido;
}

char* leerParteBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock, uint64_t byteInicio, uint64_t byteFin) {
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, numBlock);
	return leerParteBloqueGlobal(numBloqueGlobal, byteInicio, byteFin);
}

char* leerParteBloqueGlobal(uint32_t numBloque, uint64_t byteInicio, uint64_t byteFin) {
	printfCUCA("Tengo que leer parte del bloque %d, desde el byte %d hasta el %d.\n", numBloque, (uint32_t) byteInicio, (uint32_t) byteFin);
	char* contenidoAux = leerBloqueGlobal(numBloque);
	char* contenido = (char*) malloc(byteFin - byteInicio); //TODO COMPROBAR QUE NO SEA byteFin - byteInicio + 1
	printfCUCA("Tengo que leer %d bytes.\n", (uint32_t) (byteFin - byteInicio));
	memcpy(contenido, contenidoAux + byteInicio, byteFin - byteInicio);
	free(contenidoAux);
	return contenido;
}

uint8_t escribirBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock, char* contenido) {
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, numBlock);
	return escribirBloqueGlobal(numBloqueGlobal, contenido);
}

uint8_t escribirBloqueGlobal(uint32_t numBlock, char* contenido) {
	printfCUCA("Tengo que escribir completamente el bloque %d.\n", numBlock);
	printfCUCA("> Escribo el bloque [%d]\n", (uint32_t) numBlock);
	uint32_t blockSize = staticSuperBlock.blockSize;
	//guardo el bloque en la cache
	char* key = obtenerKeyBloque(numBlock);
	almacenarDatoEnCache(key, strlen(key), contenido, blockSize, 0, 0);
	escribirBytes((off_t) numBlock * blockSize, (size_t) blockSize, contenido);
	return 0;
}

uint8_t escribirParteBloqueLocal(uint64_t numBlockGroup, uint64_t numBlock, uint64_t byteInicio, uint64_t byteFin, char* contenido) {
	uint64_t numBloqueGlobal = deBloqueLocalAGlobal(numBlockGroup, numBlock);
	return escribirParteBloqueGlobal(numBloqueGlobal, byteInicio, byteFin, contenido);
}

uint8_t escribirParteBloqueGlobal(uint32_t numBloque, uint64_t byteInicio, uint64_t byteFin, char* contenido) {
	printfCUCA("Tengo que escribir parte del bloque %d, desde el byte %d hasta el %d.\n", numBloque, (uint32_t) byteInicio, (uint32_t) byteFin);
	char* contenidoAux = leerBloqueGlobal(numBloque);
	printfCUCA("Tengo que escribir %d bytes.\n", (uint32_t) (byteFin - byteInicio));
	memcpy(contenidoAux + byteInicio, contenido, byteFin - byteInicio); //TODO COMPROBAR QUE NO SEA byteFin - byteInicio + 1
	escribirBloqueGlobal(numBloque, contenidoAux);
	free(contenidoAux);
	return 0;
}

uint64_t deBloqueLocalAGlobal(uint64_t numBlockGroup, uint64_t numBlock) {
	//TODO REVISAR
	return staticGroupDescriptorTable[numBlockGroup].blockBitmap + numBlock;
}

uint32_t deBloqueGlobalALocal(uint8_t numBlockGroup, uint32_t numBlock) {
	return (numBlock - staticGroupDescriptorTable[numBlockGroup].blockBitmap);
}

//--------------------------------------------------
//LECTURA Y ESCRITURA DE ESTRUCTURAS EN EL DISCO
//--------------------------------------------------
//--------------------------------------------------
//LECTURA DEL SUPERBLOQUE
//--------------------------------------------------

superBlock_t leerSuperBlock(void) {
	char* contenido;
	char* key = malloc(strlen("superblock") + 1);
	memset(key, '\0', strlen("superblock") + 1);
	memcpy(key, "superblock", strlen("superblock"));
	size_t valueSize;
	uint32_t flags;
	memcached_return_t errorCache;
	contenido = obtenerDatoDeCache(key, strlen(key), &valueSize, &flags, &errorCache);
	if (contenido == NULL) {
		//el dato no estaba en la cache, lo leo del disco y lo guardo en la cache
		contenido = leerBytes(1024, 1024);
		errorCache = almacenarDatoEnCache(key, strlen(key), contenido, 1024, 0, 0);
	}
	free(key);
	superBlock_t superBloque;
	memcpy(&superBloque, contenido, 1024);
	free(contenido);
	if (staticSuperBlock.inicializado == 0) {
		staticSuperBlock.inicializado = 1;
		staticSuperBlock.rwlockSuperBlock = malloc(sizeof(pthread_rwlock_t));
		pthread_rwlock_init(staticSuperBlock.rwlockSuperBlock, NULL);
		staticSuperBlock.inodesCount = superBloque.inodesCount;
		staticSuperBlock.blocksCount = superBloque.blocksCount;
		staticSuperBlock.reservedBlocksCount = superBloque.reservedBlocksCount;
		staticSuperBlock.firstDataBlock = superBloque.firstDataBlock;
		staticSuperBlock.blockSize = 1024 * potencia(2, superBloque.blockSize);
		staticSuperBlock.fragmentSize = 1024 * potencia(2, superBloque.fragmentSize);
		staticSuperBlock.blocksPerGroup = superBloque.blocksPerGroup;
		staticSuperBlock.fragmentsPerGroup = superBloque.fragmentsPerGroup;
		staticSuperBlock.inodesPerGroup = superBloque.inodesPerGroup;
		staticSuperBlock.firstInode = superBloque.firstInode;
		staticSuperBlock.inodeSize = superBloque.inodeSize;
		staticSuperBlock.superBlockGroup = superBloque.superBlockGroup;
	}
	printfCUCA("===============================================================================\n");
	printfCUCA("                 > CONTENIDO DEL PRIMER SUPERBLOQUE DEL DISCO <                \n");
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> Cantidad total de i-nodos: [%d]\n", superBloque.inodesCount);
	printfCUCA("> Cantidad total de bloques: [%d]\n", superBloque.blocksCount);
	printfCUCA("> Cantidad de bloques reservados: [%d]\n", superBloque.reservedBlocksCount);
	printfCUCA("> Cantidad de bloques libres: [%d]\n", superBloque.freeBlocksCount);
	printfCUCA("> Cantidad de i-nodos libres: [%d]\n", superBloque.freeInodesCount);
	printfCUCA("> Primer bloque de datos: [%d]\n", superBloque.firstDataBlock);
	printfCUCA("> Tamaño de los bloques (1024<<): [%d]\n", superBloque.blockSize);
	printfCUCA("> Tamaño de los fragmentos (1024<<): [%d]\n", superBloque.fragmentSize);
	printfCUCA("> Cantidad de bloques por grupo de bloques: [%d]\n", superBloque.blocksPerGroup);
	printfCUCA("> Cantidad de fragmentos por grupo de bloques: [%d]\n", superBloque.fragmentsPerGroup);
	printfCUCA("> Cantidad de i-nodos por grupo de bloques: [%d]\n", superBloque.inodesPerGroup);
	printfCUCA("> Último tiempo de montado: [%d]\n", superBloque.mTime);
	printfCUCA("> Último tiempo de acceso para escritura: [%d]\n", superBloque.wTime);
	printfCUCA("> Cantidad de veces que se montó el file system: [%d]\n", superBloque.mntCount);
	printfCUCA("> Máxima cantidad de montajes permitidos sin verificacion: [%d]\n", superBloque.mntMaxCount);
	//printfCUCA("> Magic number: [%d]\n", superBloque.magic);
	printfCUCA("> Estado del file system: [%d]\n", superBloque.state);
	printfCUCA("> Manejo de errores: [%d]\n", superBloque.errors);
	printfCUCA("> Nivel de menor revision: [%d]\n", superBloque.minorRevLevel);
	printfCUCA("> Último chequeo: [%d]\n", superBloque.lastCheck);
	printfCUCA("> Máxima cantidad de intervalos de tiempo entre chequeos: [%d]\n", superBloque.checkInterval);
	printfCUCA("> Sistema Operativo: [%d]\n", superBloque.creatorOS);
	printfCUCA("> Nivel de revisión: [%d]\n", superBloque.revLevel);
	//printfCUCA("> defResUID: [%d]\n", superBloque.defResUID);
	//printfCUCA("> defResGID: [%d]\n", superBloque.defResGID);
	printfCUCA("> Primer i-nodo accesible: [%d]\n", superBloque.firstInode);
	printfCUCA("> Tamaño de los i-nodos: [%d]\n", superBloque.inodeSize);
	printfCUCA("> Grupo de super bloque: [%d]\n", superBloque.superBlockGroup);
	printfCUCA("> Funcionalidades compatibles: [%d]\n", superBloque.featureCompat);
	printfCUCA("> Funcionalidades incompatibles: [%d]\n", superBloque.featureIncompat);
	//printfCUCA("> feature ROcompat: [%d]\n", superBloque.featureROCompat);
	//printfCUCA("UUID: [%s]\n", superBloque.UUID);
	printfCUCA("> Nombre del volúmen: [%s]\n", superBloque.volumeName);
	printfCUCA("> Último directorio montado: [%s]\n", superBloque.lastMountedDirectory);
	//printfCUCA("> algoBitmap: [%d]\n", superBloque.algoBitmap);
	//printfCUCA("preallocBlocks: [%d]\n", superBloque.preallocBlocks);
	//printfCUCA("preallocDirBlocks: [%d]\n", superBloque.preallocDirBlocks);
	printfCUCA("> Alineamiento: [%d]\n", superBloque.alignment);
	//printfCUCA("Journal UUID: [%s]\n", superBloque.journalUUID);
	//printfCUCA("Journal INum: [%d]\n", superBloque.journalINum);
	//printfCUCA("Journal Dev: [%d]\n", superBloque.journalDev);
	printfCUCA("> Último huérfano: [%d]\n", superBloque.lastOrphan);
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("              > DATOS GUARDADOS EN MEMORIA SOBRE EL SUPERBLOQUE <              \n");
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> Cantidad total de i-nodos: [%d]\n", staticSuperBlock.inodesCount);
	printfCUCA("> Cantidad total de bloques: [%d]\n", staticSuperBlock.blocksCount);
	printfCUCA("> Cantidad de bloques reservados: [%d]\n", staticSuperBlock.reservedBlocksCount);
	printfCUCA("> Primer bloque de datos: [%d]\n", staticSuperBlock.firstDataBlock);
	printfCUCA("> Tamanio de los bloques (1024<<): [%d]\n", staticSuperBlock.blockSize);
	printfCUCA("> Tamanio de los fragmentos (1024<<): [%d]\n", staticSuperBlock.fragmentSize);
	printfCUCA("> Cantidad de bloques por grupo de bloques: [%d]\n", staticSuperBlock.blocksPerGroup);
	printfCUCA("> Cantidad de fragmentos por grupo de bloques: [%d]\n", staticSuperBlock.fragmentsPerGroup);
	printfCUCA("> Cantidad de i-nodos por grupo de bloques: [%d]\n", staticSuperBlock.inodesPerGroup);
	printfCUCA("> Primer i-nodo accesible: [%d]\n", staticSuperBlock.firstInode);
	printfCUCA("> Tamaño de los i-nodos: [%d]\n", staticSuperBlock.inodeSize);
	printfCUCA("> Grupo de super bloque: [%d]\n", staticSuperBlock.superBlockGroup);
	return superBloque;
}

void escribirSuperBloque(superBlock_t superBloque) {
	char* bufferSuperBloque = (char*) malloc(1024);
	memcpy(bufferSuperBloque, &superBloque, 1024);
	char* key = malloc(strlen("superblock") + 1);
	memset(key, '\0', strlen("superblock") + 1);
	memcpy(key, "superblock", strlen("superblock"));
	almacenarDatoEnCache(key, strlen(key), bufferSuperBloque, 1024, 0, 0);
	free(key);
	escribirBytes(1024, 1024, bufferSuperBloque);
	free(bufferSuperBloque);
}

//--------------------------------------------------
//LECTURA DE LA GROUP DESCRIPTOR TABLE
//--------------------------------------------------

uint16_t cantBlockGroups(void) {
	//TODO REVISAR
	return staticSuperBlock.inodesCount / staticSuperBlock.inodesPerGroup;
}

uint64_t groupDescriptorTableSize(void) {
	return cantBlockGroups() * sizeof(groupDescriptor_t);
}

uint8_t bloqueInicioPrimerGroupDescriptorTable(void) {
	//TODO REVISAR
	return staticSuperBlock.firstDataBlock + 1;
}

uint16_t cantBloquesGroupDescriptorTable(void) {
	div_t division = div(groupDescriptorTableSize(), staticSuperBlock.blockSize);
	uint8_t cantBloques = division.quot;
	if (division.rem != 0) {
		cantBloques++;
	}
	return cantBloques;
}

groupDescriptor_t* leerGroupDescriptorTable(void) {
	//leo los bloques correspondientes
	char* contenido = (char*) malloc(groupDescriptorTableSize());
	uint32_t i;
	uint32_t bloqueInicio = bloqueInicioPrimerGroupDescriptorTable();
	uint16_t cantBloques = cantBloquesGroupDescriptorTable();
	for (i = 0; i < cantBloques - 1; i++) {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	uint16_t resto = div(groupDescriptorTableSize(), staticSuperBlock.blockSize).rem;
	if (resto != 0) {
		char* contenidoAux = leerParteBloqueGlobal(bloqueInicio + i, 0, resto);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, resto);
		free(contenidoAux);
	} else {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	groupDescriptor_t *groupDescriptor = (groupDescriptor_t*) malloc(groupDescriptorTableSize());
	memcpy(groupDescriptor, contenido, groupDescriptorTableSize());
	free(contenido);
	printf("-------------------------------------------------------------------------------\n");
	printf("           > DATOS DE LA GROUP DESCRIPTOR TABLE OBTENIDOS DEL DISCO <          \n");
	for (i = 0; i < cantBlockGroups(); i++) {
		printf("> Grupo [%d]:\n", i);
		printf("  --> Primer bloque del group bitmap: [%d]\n", groupDescriptor[i].blockBitmap);
		printf("  --> Primer bloque del i-node bitmap: [%d]\n", groupDescriptor[i].inodeBitmap);
		printf("  --> Primer bloque de la i-node table: [%d]\n", groupDescriptor[i].inodeTable);
		printf("  --> Cantidad de bloques libres: [%d]\n", groupDescriptor[i].freeBlocksCount);
		printf("  --> Cantidad de i-nodos libres: [%d]\n", groupDescriptor[i].freeInodesCount);
		printf("  --> Cantidad de i-nodos dedicados a directorios: [%d]\n", groupDescriptor[i].dirsCount);
		printf("  --> Pad: [%d]\n", groupDescriptor[i].pad);
	}
	if (staticGroupDescriptorTable == NULL) {
		printf("-------------------------------------------------------------------------------\n");
		printf("                  > CARGO LA STATIC GROUP DESCRIPTOR TABLE <                   \n");
		cargarStaticGroupDescriptorTable(groupDescriptor);
		cargarGroupDescriptorTableAux(groupDescriptor);
	}
	return groupDescriptor;
}

void escribirGroupDescriptorTable(groupDescriptor_t* groupDescriptorTable) {
	char* bufferGroupDescriptorTable = (char*) malloc(groupDescriptorTableSize());
	memcpy(bufferGroupDescriptorTable, groupDescriptorTable, groupDescriptorTableSize());
	uint32_t i;
	uint32_t bloqueInicio = bloqueInicioPrimerGroupDescriptorTable();
	uint16_t cantBloques = cantBloquesGroupDescriptorTable();
	for (i = 0; i < cantBloques - 1; i++) {
		printfCUCA("> Tengo que escribir el bloque [%d] que es el [%d] de la tabla de descriptores de grupos\n", bloqueInicio + i, i);
		escribirBloqueGlobal(bloqueInicio + i, bufferGroupDescriptorTable + (i * staticSuperBlock.blockSize));
	}
	uint16_t resto = div(groupDescriptorTableSize(), staticSuperBlock.blockSize).rem;
	//TODO esto puede traer el mismo error que el offset de la lectura de bloques en caso que el offset sea igual al tamanio de bloques
	if (resto != 0) {
		printfCUCA("> Tengo que escribir [%d] bytes del bloque [%d] que es el [%d] de la tabla de descriptores de grupos\n", resto, bloqueInicio + i, i);
		escribirParteBloqueGlobal(bloqueInicio + i, 0, resto, bufferGroupDescriptorTable + (i * staticSuperBlock.blockSize));
	} else {
		printfCUCA("> Tengo que escribir el bloque [%d] que es el [%d] de la tabla de descriptores de grupos\n", bloqueInicio + i, i);
		escribirBloqueGlobal(bloqueInicio + i, bufferGroupDescriptorTable + (i * staticSuperBlock.blockSize));
	}
	free(bufferGroupDescriptorTable);
}

void cargarStaticGroupDescriptorTable(groupDescriptor_t* groupDescriptorTable) {
	staticGroupDescriptorTable = (staticGroupDescriptor_t*) malloc(cantBlockGroups() * sizeof(staticGroupDescriptor_t));
	uint16_t i;
	for (i = 0; i < cantBlockGroups(); i++) {
		printf("olAolaola\n");
		staticGroupDescriptorTable[i].blockBitmap = groupDescriptorTable[i].blockBitmap;
		staticGroupDescriptorTable[i].rwlockBlockBitmap = malloc(sizeof(pthread_rwlock_t));
		pthread_rwlock_init(staticGroupDescriptorTable[i].rwlockBlockBitmap, NULL);
		staticGroupDescriptorTable[i].inodeBitmap = groupDescriptorTable[i].inodeBitmap;
		staticGroupDescriptorTable[i].rwlockInodeBitmap = malloc(sizeof(pthread_rwlock_t));
		pthread_rwlock_init(staticGroupDescriptorTable[i].rwlockInodeBitmap, NULL);
		staticGroupDescriptorTable[i].inodeTable = groupDescriptorTable[i].inodeTable;
		staticGroupDescriptorTable[i].rwlockInodeTable = malloc(sizeof(pthread_rwlock_t));
		pthread_rwlock_init(staticGroupDescriptorTable[i].rwlockInodeTable, NULL);
	}
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("          > DATOS DE LA GROUP DESCRIPTOR TABLE GUARDADOS EN MEMORIA <          \n");
	for (i = 0; i < cantBlockGroups(); i++) {
		printfCUCA("> Grupo [%d]:\n", i);
		printfCUCA("  --> Primer bloque del group bitmap: [%d]\n", staticGroupDescriptorTable[i].blockBitmap);
		printfCUCA("  --> Primer bloque del i-node bitmap: [%d]\n", staticGroupDescriptorTable[i].inodeBitmap);
		printfCUCA("  --> Primer bloque de la i-node table: [%d]\n", staticGroupDescriptorTable[i].inodeTable);
	}
}

void cargarGroupDescriptorTableAux(groupDescriptor_t* groupDescriptorTable) {
	groupDescriptorTableAux = (groupDescriptor_t*) malloc(groupDescriptorTableSize());
	uint16_t i;
	for (i = 0; i < cantBlockGroups(); i++) {
		printf("olAolaola\n");
		t_bitarray* blockBitmap = leerBlockBitmap(i);
		groupDescriptorTableAux[i].freeBlocksCount = cantidadDeBloquesLibresEnBlockGroup(groupDescriptorTable, i, blockBitmap);
	}
}

//--------------------------------------------------
//LECTURA Y ESCRITURA DE BITMAPS
//--------------------------------------------------
//--------------------------------------------------
//LECTURA Y ESCRITURA DEL BLOCK BITMAP
//--------------------------------------------------

uint64_t blockBitmapSize(void) {
	//TODO revisar
	uint64_t cantBytesBitmap = staticSuperBlock.blocksPerGroup / 8;
	if ((staticSuperBlock.blocksPerGroup % 8) != 0) {
		cantBytesBitmap++;
	}
	return cantBytesBitmap;
}

uint16_t cantBloquesBlockBitmap(void) {
	div_t division = div(blockBitmapSize(), staticSuperBlock.blockSize);
	uint8_t cantBloques = division.quot;
	if (division.rem != 0) {
		cantBloques++;
	}
	return cantBloques;
}

t_bitarray* leerBlockBitmap(uint8_t numBlockGroup) {
	char* contenido = (char*) malloc(blockBitmapSize());
	uint32_t i = 0;
	uint32_t bloqueInicio = staticGroupDescriptorTable[numBlockGroup].blockBitmap;
	uint16_t cantBloques = cantBloquesBlockBitmap();
	for (i = 0; i < cantBloques - 1; i++) {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	uint16_t resto = div(blockBitmapSize(), staticSuperBlock.blockSize).rem;
	if (resto != 0) {
		char* contenidoAux = leerParteBloqueGlobal(bloqueInicio + i, 0, resto);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, resto);
		free(contenidoAux);
	} else {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	return bitarray_create(contenido, blockBitmapSize());
}

uint8_t escribirBlockBitmap(uint8_t numBlockGroup, t_bitarray* blockBitmap) {
	char* bufferBlockBitmap = blockBitmap->bitarray;
	uint32_t i = 0;
	uint32_t bloqueInicio = staticGroupDescriptorTable[numBlockGroup].blockBitmap;
	uint16_t cantBloques = cantBloquesBlockBitmap();
	for (i = 0; i < cantBloques - 1; i++) {
		escribirBloqueGlobal(bloqueInicio + i, bufferBlockBitmap + (i * staticSuperBlock.blockSize));
	}
	uint16_t resto = div(blockBitmapSize(), staticSuperBlock.blockSize).rem;
	if (resto != 0) {
		escribirParteBloqueGlobal(bloqueInicio + i, 0, resto, bufferBlockBitmap + (i * staticSuperBlock.blockSize));
	} else {
		escribirBloqueGlobal(bloqueInicio + i, bufferBlockBitmap + (i * staticSuperBlock.blockSize));
	}
	return 0;
}

bool estaOcupadoBloque(t_bitarray* blockBitmap, uint64_t numBloque) {
	return bitarray_test_bit(blockBitmap, numBloque);
}

void liberarBloqueOcupadoEnBitmap(t_bitarray* blockBitmap, uint64_t numBloque) {
	bitarray_clean_bit(blockBitmap, numBloque);
}

void ocuparBloqueLibreEnBitmap(t_bitarray* blockBitmap, uint64_t numBloque) {
	bitarray_set_bit(blockBitmap, numBloque);
}

/*int8_t liberarBloqueOcupado(uint8_t numBlockGroup, uint32_t numBloque) {
 printfCUCA("Voy a liberar el bloque %d del grupo %d.\n", numBloque, numBlockGroup);
 t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroup);
 liberarBloqueOcupadoEnBitmap(blockBitmap, numBloque);
 escribirBlockBitmap(numBlockGroup, blockBitmap);
 free(blockBitmap->bitarray);
 bitarray_destroy(blockBitmap);
 superBlock_t superBloque = leerSuperBlock();
 superBloque.freeBlocksCount++;
 escribirSuperBloque(superBloque);
 groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
 groupDescriptorTable[numBlockGroup].freeBlocksCount++;
 escribirGroupDescriptorTable(groupDescriptorTable);
 return 0;
 }*/

/*uint8_t liberarNBloquesOcupados(nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin, uint8_t numBlockGroup) {
 pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroup].rwlockBlockBitmap);
 t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroup);
 uint32_t i;
 for (i = 0; *colaBloquesFte != NULL; i++) {
 uint32_t numBloque = desencolarNumBloque(colaBloquesFte, colaBloquesFin);
 liberarBloqueOcupadoEnBitmap(blockBitmap, numBloque);
 }
 escribirBlockBitmap(numBlockGroup, blockBitmap);
 pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroup].rwlockBlockBitmap);

 free(blockBitmap->bitarray);
 bitarray_destroy(blockBitmap);
 pthread_rwlock_wrlock(staticSuperBlock.rwlockSuperBlock);
 superBlock_t superBloque = leerSuperBlock();
 superBloque.freeBlocksCount += i;
 escribirSuperBloque(superBloque);
 pthread_rwlock_unlock(staticSuperBlock.rwlockSuperBlock);

 pthread_rwlock_wrlock(&rwlockGroupDescriptorTable);
 groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
 groupDescriptorTable[numBlockGroup].freeBlocksCount += i;
 escribirGroupDescriptorTable(groupDescriptorTable);
 pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

 return 0;
 }*/

uint8_t perteneceBloqueABlockGroup(uint8_t numBlockGroup, uint32_t numBloque) {
	uint32_t numBloqueAux = deBloqueGlobalALocal(numBlockGroup, numBloque);
	if (numBloqueAux <= staticSuperBlock.blocksPerGroup) {
		return 1;
	} else {
		return 0;
	}
}

uint8_t liberarNBloquesOcupadosGlobales(nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin) {
	pthread_rwlock_wrlock(&rwlockGroupDescriptorTable);
	groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
	uint8_t numBlockGroupActual;
	for (numBlockGroupActual = 0; (numBlockGroupActual < cantBlockGroups()) && (*colaBloquesFte != NULL); numBlockGroupActual++) {
		pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroupActual].rwlockBlockBitmap);
		t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroupActual);
		uint32_t i;
		nodoNumBloque_t* aux = *colaBloquesFte;
		for (i = 0; aux != NULL; i++) {
			if (perteneceBloqueABlockGroup(numBlockGroupActual, aux->numBloque)) {
				uint32_t numBloque = desencolarNumBloque(colaBloquesFte, colaBloquesFin);
				deBloqueGlobalALocal(numBlockGroupActual, numBloque);
				liberarBloqueOcupadoEnBitmap(blockBitmap, numBloque);
				aux = *colaBloquesFte;
			} else {
				aux = aux->sig;
			}
		}
		escribirBlockBitmap(numBlockGroupActual, blockBitmap);
		pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroupActual].rwlockBlockBitmap);

		free(blockBitmap->bitarray);
		bitarray_destroy(blockBitmap);
		pthread_rwlock_wrlock(staticSuperBlock.rwlockSuperBlock);
		superBlock_t superBloque = leerSuperBlock();
		superBloque.freeBlocksCount += i;
		escribirSuperBloque(superBloque);
		pthread_rwlock_unlock(staticSuperBlock.rwlockSuperBlock);

		groupDescriptorTable[numBlockGroupActual].freeBlocksCount += i;
		groupDescriptorTableAux[numBlockGroupActual].freeBlocksCount += i;
	}
	escribirGroupDescriptorTable(groupDescriptorTable);
	pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

	return 0;
}

int64_t buscarBloqueLibreEnBitmap(t_bitarray* blockBitmap) {
	uint64_t encontrado = -1, i;
	for (i = 0; (i < staticSuperBlock.blocksPerGroup) && (encontrado == -1); i++) {
		if (!(estaOcupadoBloque(blockBitmap, i))) {
			printfCUCA("> El bloque [%d] está libre\n", (uint32_t) i);
			encontrado = i;
		} else {
			//printfCUCA("El bloque [%d] esta ocupado.\n", (uint32_t) i);
		}
	}
	return encontrado;
}

uint8_t buscarBloqueLibreEnBitmapAPartirDe(t_bitarray* blockBitmap, uint64_t offset, uint32_t *numBlock) {
	uint8_t encontrado = 0;
	uint32_t i;
	for (i = offset; (i < staticSuperBlock.blocksPerGroup) && (!encontrado); i++) {
		uint64_t iAux = i;
		if (!(estaOcupadoBloque(blockBitmap, iAux))) {
			printf("<buscarBloqueLibreEnBitmapAPartirDe> El bloque %d está libre\n", i);
			*numBlock = i;
			encontrado = 1;
		} else {
			printfCUCA("<buscarBloqueLibreEnBitmapAPartirDe> El bloque %d está ocupado\n", i);
		}
	}
	if (encontrado) {
		return 0;
	} else {
		return 1;
	}
}

/*int64_t buscarYOcuparBloqueLibre(uint8_t numBlockGroup) {
 t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroup);
 int64_t numBlock = buscarBloqueLibreEnBitmap(blockBitmap);
 if (numBlock >= 0 && numBlock < staticSuperBlock.blocksPerGroup) {
 ocuparBloqueLibreEnBitmap(blockBitmap, numBlock);
 escribirBlockBitmap(numBlockGroup, blockBitmap);
 free(blockBitmap->bitarray);
 bitarray_destroy(blockBitmap);
 superBlock_t superBloque = leerSuperBlock();
 superBloque.freeBlocksCount--;
 escribirSuperBloque(superBloque);
 groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
 groupDescriptorTable[numBlockGroup].freeBlocksCount--;
 escribirGroupDescriptorTable(groupDescriptorTable);
 return numBlock;
 } else {
 return -1;
 }
 }*/

void encolarNumBloque(nodoNumBloque_t** colaFte, nodoNumBloque_t** colaFin, uint32_t numBlock) {
	nodoNumBloque_t* aux = malloc(sizeof(nodoNumBloque_t));
	aux->numBloque = numBlock;
	aux->sig = NULL;
	if (*colaFte == NULL) {
		*colaFte = aux;
		*colaFin = aux;
	} else {
		(*colaFin)->sig = aux;
		(*colaFin) = aux;
	}
}

uint32_t desencolarNumBloque(nodoNumBloque_t** colaFte, nodoNumBloque_t** colaFin) {
	nodoNumBloque_t* aux = *colaFte;
	(*colaFte) = (*colaFte)->sig;
	if (*colaFte == NULL) {
		*colaFin = NULL;
	}
	uint32_t numBloque = aux->numBloque;
	free(aux);
	return numBloque;
}

/*uint8_t buscarYOcuparNBloquesLibres(nodoNumBloque_t** colaFte, nodoNumBloque_t** colaFin, uint8_t numBlockGroup, uint32_t cantBloques) {

 pthread_rwlock_wrlock(&rwlockGroupDescriptorTable);
 groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
 printfCUCA("<buscarYOcuparNBloquesLibres> numBlockGroup: %d \n", numBlockGroup);
 if (groupDescriptorTable[numBlockGroup].freeBlocksCount >= cantBloques) {

 pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroup].rwlockBlockBitmap);
 t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroup);
 uint32_t i;
 uint8_t error = 0;
 uint64_t offset = 0;
 for (i = 0; !error && i < cantBloques; i++) {
 int64_t numBlock = buscarBloqueLibreEnBitmapAPartirDe(blockBitmap, offset);
 if (numBlock >= 0 && numBlock < staticSuperBlock.blocksPerGroup) {
 offset = numBlock + 1;
 ocuparBloqueLibreEnBitmap(blockBitmap, numBlock);
 encolarNumBloque(colaFte, colaFin, (uint32_t) numBlock);
 } else {
 error = 1;
 }
 }
 if (!error) {
 escribirBlockBitmap(numBlockGroup, blockBitmap);
 pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroup].rwlockBlockBitmap);

 free(blockBitmap->bitarray);
 bitarray_destroy(blockBitmap);

 groupDescriptorTable[numBlockGroup].freeBlocksCount -= cantBloques;
 escribirGroupDescriptorTable(groupDescriptorTable);
 free(groupDescriptorTable);
 pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

 pthread_rwlock_wrlock(staticSuperBlock.rwlockSuperBlock);
 superBlock_t superBloque = leerSuperBlock();
 superBloque.freeBlocksCount -= cantBloques;
 escribirSuperBloque(superBloque);
 pthread_rwlock_unlock(staticSuperBlock.rwlockSuperBlock);

 return 0;
 } else {
 free(groupDescriptorTable);
 pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroup].rwlockBlockBitmap);

 pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

 while (*colaFte != NULL) {
 nodoNumBloque_t* aux = *colaFte;
 (*colaFte) = (*colaFte)->sig;
 free(aux);
 }
 return 1;
 }
 } else {
 free(groupDescriptorTable);
 pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

 return 1;
 }
 }*/
uint32_t cantidadBloquesOcupadosEnBitmap(t_bitarray* blockBitmap) {
	uint32_t multiplosDe64 = (blockBitmapSize() * 8) / 64;
	uint32_t restoDe64 = (blockBitmapSize() * 8) % 64;
	uint32_t i, j, retorno;
	uint64_t* bitmap = (uint64_t*) (*blockBitmap).bitarray;
	for (i = 0, j = 0, retorno = 0; i < multiplosDe64 * 64; i += 64, j++) {
		if (bitmap[j] == 18446744073709551615) {
			retorno += 64;
		} else if (bitmap[j] != 0) {
			uint8_t iAux;
			for (iAux = 0; iAux < 64; iAux++) {
				if (bitarray_test_bit(blockBitmap, i + iAux)) {
					retorno++;
				}
			}
		}
	}
	if (restoDe64 != 0) {
		for (; i < restoDe64; i++) {
			if (bitarray_test_bit(blockBitmap, i)) {
				retorno++;
			}
		}
	}
	return retorno;
}

uint32_t cantidadDeBloquesLibresEnBlockGroup(groupDescriptor_t* groupDescriptorTable, uint8_t numBlockGroup, t_bitarray* blockBitmap) {
	if (groupDescriptorTable[numBlockGroup].freeBlocksCount == 0) { //TODO PODRIA NECESITAR CAMBIARSE POR UN UINT32_T
		return 0;
	} else {
		if (numBlockGroup == (cantBlockGroups() - 1)) {
			return groupDescriptorTable[numBlockGroup].freeBlocksCount;
		} else {
			uint32_t cantBloquesOcupados = cantidadBloquesOcupadosEnBitmap(blockBitmap);
			uint32_t totalBloquesGrupo = cantBloquesOcupados + groupDescriptorTable[numBlockGroup].freeBlocksCount;
			uint32_t maxCantBloquesPosiblesGrupo = groupDescriptorTable[numBlockGroup + 1].blockBitmap - groupDescriptorTable[numBlockGroup].blockBitmap;
			if (totalBloquesGrupo > maxCantBloquesPosiblesGrupo) {
				return maxCantBloquesPosiblesGrupo - cantBloquesOcupados;
			} else {
				return totalBloquesGrupo - cantBloquesOcupados;
			}
		}
	}
}

uint8_t buscarYOcuparNBloquesLibresGlobales(nodoNumBloque_t** colaFte, nodoNumBloque_t** colaFin, uint32_t cantBloques) {
	uint8_t numBlockGroupActual = 0;
	uint32_t cantBloquesFaltantes = cantBloques;
	printf("<buscarYOcuparNBloquesLibresGlobales> cantBloquesFaltantes: %d\n", cantBloquesFaltantes);
	pthread_rwlock_wrlock(&rwlockGroupDescriptorTable);
	uint8_t error = 0;
	groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
	for (numBlockGroupActual = 0; numBlockGroupActual < cantBlockGroups() && cantBloquesFaltantes > 0 && !error; numBlockGroupActual++) {
		printf("<buscarYOcuparNBloquesLibresGlobales> numBlockGroupActual: %d\n", numBlockGroupActual);
		uint32_t cantBloquesEnGroup = 0;
		pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroupActual].rwlockBlockBitmap);
		t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroupActual);
		uint32_t maxCantBloques = groupDescriptorTableAux[numBlockGroupActual].freeBlocksCount;
		if (maxCantBloques >= cantBloquesFaltantes) {
			cantBloquesEnGroup = cantBloquesFaltantes;
		} else {
			cantBloquesEnGroup = maxCantBloques;
		}
		printf("<buscarYOcuparNBloquesLibresGlobales> cantBloquesEnGroup: %d\n", cantBloquesEnGroup);
		if (cantBloquesEnGroup > 0) {
			uint32_t i;
			uint64_t offset = 0;
			for (i = 0; !error && i < cantBloquesEnGroup; i++) {
				uint32_t numBlock = 0;
				error = buscarBloqueLibreEnBitmapAPartirDe(blockBitmap, offset, &numBlock);
				printf("<buscarYOcuparNBloquesLibresGlobales> numBlock: %d\n", numBlock);
				if (!error && numBlock >= 0 && numBlock < staticSuperBlock.blocksPerGroup) {
					offset = numBlock + 1;
					ocuparBloqueLibreEnBitmap(blockBitmap, numBlock);
					uint32_t numBloqueGlobal = (uint32_t) deBloqueLocalAGlobal(numBlockGroupActual, (uint64_t) numBlock);
					encolarNumBloque(colaFte, colaFin, numBloqueGlobal);
				} else {
					printf("<buscarYOcuparNBloquesLibresGlobales> Error al buscar un bloque libre en el bitmap\n");
				}
			}
			if (!error) {
				escribirBlockBitmap(numBlockGroupActual, blockBitmap);

				free(blockBitmap->bitarray);
				bitarray_destroy(blockBitmap);

				printf("<buscarYOcuparNBloquesLibresGlobales> numBlockGroupActual: %d\n", numBlockGroupActual);
				printf("<buscarYOcuparNBloquesLibresGlobales> cantBloquesEnGroup: %d\n", cantBloquesEnGroup);

				groupDescriptorTable[numBlockGroupActual].freeBlocksCount -= cantBloquesEnGroup;
				groupDescriptorTableAux[numBlockGroupActual].freeBlocksCount -= cantBloquesEnGroup;
				cantBloquesFaltantes -= cantBloquesEnGroup;
			}
		}
		pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroupActual].rwlockBlockBitmap);
	}
	printf("<buscarYOcuparNBloquesLibresGlobales> cantBloquesFaltantes: %d\n", cantBloquesFaltantes);
	if (!error && cantBloquesFaltantes == 0) {
		escribirGroupDescriptorTable(groupDescriptorTable);
		free(groupDescriptorTable);
		pthread_rwlock_wrlock(staticSuperBlock.rwlockSuperBlock);
		superBlock_t superBloque = leerSuperBlock();
		superBloque.freeBlocksCount -= cantBloques;
		escribirSuperBloque(superBloque);
		pthread_rwlock_unlock(staticSuperBlock.rwlockSuperBlock);

		pthread_rwlock_unlock(&rwlockGroupDescriptorTable);
		return 0;
	} else {
		free(groupDescriptorTable);
		for (numBlockGroupActual = 0; numBlockGroupActual < cantBlockGroups() && *colaFte != NULL; numBlockGroupActual++) {
			pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroupActual].rwlockBlockBitmap);
			t_bitarray* blockBitmap = leerBlockBitmap(numBlockGroupActual);
			uint32_t i;
			nodoNumBloque_t* aux = *colaFte;
			for (i = 0; aux != NULL; i++) {
				if (perteneceBloqueABlockGroup(numBlockGroupActual, aux->numBloque)) {
					uint32_t numBloque = desencolarNumBloque(colaFte, colaFin);
					deBloqueGlobalALocal(numBlockGroupActual, numBloque);
					liberarBloqueOcupadoEnBitmap(blockBitmap, numBloque);
					aux = *colaFte;
				} else {
					aux = aux->sig;
				}
			}
			escribirBlockBitmap(numBlockGroupActual, blockBitmap);
			pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroupActual].rwlockBlockBitmap);

			free(blockBitmap->bitarray);
			bitarray_destroy(blockBitmap);
		}
		pthread_rwlock_unlock(&rwlockGroupDescriptorTable);
		return 1;
	}
}

//--------------------------------------------------
//LECTURA Y ESCRITURA DEL INODE BITMAP
//--------------------------------------------------

uint64_t inodeBitmapSize(void) {
	//TODO revisar
	uint64_t cantBytesBitmap = staticSuperBlock.inodesPerGroup / 8;
	if ((staticSuperBlock.inodesPerGroup % 8) != 0) {
		cantBytesBitmap++;
	}
	return cantBytesBitmap;
}

uint16_t cantBloquesInodeBitmap(void) {
	div_t division = div(inodeBitmapSize(), staticSuperBlock.blockSize);
	uint8_t cantBloques = division.quot;
	if (division.rem != 0) {
		cantBloques++;
	}
	return cantBloques;
}

t_bitarray* leerInodeBitmap(uint8_t numBlockGroup) {
	char* contenido = (char*) malloc(inodeBitmapSize());
	uint32_t i = 0;
	uint32_t bloqueInicio = staticGroupDescriptorTable[numBlockGroup].inodeBitmap;
	uint16_t cantBloques = cantBloquesInodeBitmap();
	printfCUCA("El inode bitmap tiene %d bloques.\n", cantBloques);
	for (i = 0; i < cantBloques - 1; i++) {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	uint16_t resto = div(inodeBitmapSize(), staticSuperBlock.blockSize).rem;
	if (resto != 0) {
		printfCUCA("El resto de la lectura del inode bitmap es %d.\n", resto);
		char* contenidoAux = leerParteBloqueGlobal(bloqueInicio + i, 0, resto);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, resto);
		free(contenidoAux);
	} else {
		char* contenidoAux = leerBloqueGlobal(bloqueInicio + i);
		memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
		free(contenidoAux);
	}
	return bitarray_create(contenido, inodeBitmapSize());
}

uint8_t escribirInodeBitmap(uint8_t numBlockGroup, t_bitarray* blockBitmap) {
	char* bufferInodeBitmap = blockBitmap->bitarray;
	uint32_t i = 0;
	uint32_t bloqueInicio = staticGroupDescriptorTable[numBlockGroup].inodeBitmap;
	uint16_t cantBloques = cantBloquesInodeBitmap();
	printfCUCA("El inode bitmap tiene %d bloques.\n", cantBloques);
	for (i = 0; i < cantBloques - 1; i++) {
		escribirBloqueGlobal(bloqueInicio + i, bufferInodeBitmap + (i * staticSuperBlock.blockSize));
	}
	uint16_t resto = div(inodeBitmapSize(), staticSuperBlock.blockSize).rem;
	if (resto != 0) {
		printfCUCA("El resto de la escritura del inode bitmap es %d.\n", resto);
		escribirParteBloqueGlobal(bloqueInicio + i, 0, resto, bufferInodeBitmap + (i * staticSuperBlock.blockSize));
	} else {
		escribirBloqueGlobal(bloqueInicio + i, bufferInodeBitmap + (i * staticSuperBlock.blockSize));
	}
	return 0;
}

bool estaOcupadoInodo(t_bitarray* inodeBitmap, uint64_t numInodo) {
	return bitarray_test_bit(inodeBitmap, numInodo);
}

void liberarInodoOcupadoEnBitmap(t_bitarray* inodeBitmap, uint64_t numInodo) {
	bitarray_clean_bit(inodeBitmap, numInodo);
}

void ocuparInodoLibreEnBitmap(t_bitarray* inodeBitmap, uint64_t numInodo) {
	bitarray_set_bit(inodeBitmap, numInodo);
}

int8_t liberarInodoOcupado(uint8_t numBlockGroup, uint32_t numInodo, uint8_t esDir) {
	inodeStructure_t inodo = INODE_STRUCTURE_VACIA;
	escribirInodo(inodo, numInodo + (staticSuperBlock.inodesPerGroup * numBlockGroup));

	pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroup].rwlockInodeBitmap);
	t_bitarray* inodeBitmap = leerInodeBitmap(numBlockGroup);
	liberarInodoOcupadoEnBitmap(inodeBitmap, numInodo);
	escribirInodeBitmap(numBlockGroup, inodeBitmap);
	pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroup].rwlockInodeBitmap);

	free(inodeBitmap->bitarray);
	bitarray_destroy(inodeBitmap);

	pthread_rwlock_wrlock(staticSuperBlock.rwlockSuperBlock);
	superBlock_t superBloque = leerSuperBlock();
	superBloque.freeInodesCount++;
	escribirSuperBloque(superBloque);
	pthread_rwlock_unlock(staticSuperBlock.rwlockSuperBlock);

	pthread_rwlock_wrlock(&rwlockGroupDescriptorTable);
	groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
	groupDescriptorTable[numBlockGroup].freeInodesCount++;
	if (esDir) {
		groupDescriptorTable[numBlockGroup].dirsCount--;
	}
	escribirGroupDescriptorTable(groupDescriptorTable);
	pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

	return 0;
}

int64_t buscarInodoLibreEnBitmap(t_bitarray*inodeBitmap) {
	uint64_t encontrado = -1, i;
	for (i = 0; (i < staticSuperBlock.inodesPerGroup) && (encontrado == -1); i++) {
		if (!(estaOcupadoInodo(inodeBitmap, i)))
			encontrado = i;
	}
	return encontrado;
}

int64_t buscarYOcuparInodoLibre(uint8_t numBlockGroup, uint8_t esDir) {

	pthread_rwlock_wrlock(&rwlockGroupDescriptorTable);
	groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();

	if (groupDescriptorTable[numBlockGroup].freeInodesCount >= 1) {
		pthread_rwlock_wrlock(staticGroupDescriptorTable[numBlockGroup].rwlockInodeBitmap);
		t_bitarray* inodeBitmap = leerInodeBitmap(numBlockGroup);
		int64_t numBlock = buscarInodoLibreEnBitmap(inodeBitmap);
		if (numBlock > 0) {
			ocuparInodoLibreEnBitmap(inodeBitmap, numBlock);
			escribirInodeBitmap(numBlockGroup, inodeBitmap);
			pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroup].rwlockInodeBitmap);

			free(inodeBitmap->bitarray);
			bitarray_destroy(inodeBitmap);

			groupDescriptorTable[numBlockGroup].freeInodesCount--;
			if (esDir) {
				groupDescriptorTable[numBlockGroup].dirsCount++;
			}
			escribirGroupDescriptorTable(groupDescriptorTable);
			pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

			pthread_rwlock_wrlock(staticSuperBlock.rwlockSuperBlock);
			superBlock_t superBloque = leerSuperBlock();
			superBloque.freeInodesCount--;
			escribirSuperBloque(superBloque);
			pthread_rwlock_unlock(staticSuperBlock.rwlockSuperBlock);

			return numBlock;
		} else {
			pthread_rwlock_unlock(staticGroupDescriptorTable[numBlockGroup].rwlockInodeBitmap);

			pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

			return -1;
		}
	} else {
		pthread_rwlock_unlock(&rwlockGroupDescriptorTable);

		return -1;
	}
}

int64_t buscarYOcuparInodoLibreGlobal(uint8_t* numBlockGroup, uint8_t esDir) {
	int64_t numInodoAux = -1;
	for (*numBlockGroup = 0; numInodoAux < 0 && *numBlockGroup < cantBlockGroups();) {
		numInodoAux = buscarYOcuparInodoLibre(*numBlockGroup, esDir);
		if (numInodoAux < 0) {
			(*numBlockGroup)++;
		}
	}
	return numInodoAux;
}

//--------------------------------------------------
//LECTURA DE LA INODE TABLE
//--------------------------------------------------

void imprimirContenidoInodoExtendido(inodeStructure_t inodo) {
	printfCUCA("===============================================================================\n");
	printfCUCA("|                           > CONTENIDO DEL I-NODO <                          |\n");
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("| MODO: %d", inodo.mode);
	if (inodo.mode >= 0 && inodo.mode <= 9) {
		printfCUCA("           ");
	} else if (inodo.mode > 9 && inodo.mode <= 99) {
		printfCUCA("          ");
	} else if (inodo.mode > 99 && inodo.mode <= 999) {
		printfCUCA("         ");
	} else if (inodo.mode > 999 && inodo.mode <= 9999) {
		printfCUCA("        ");
	} else if (inodo.mode > 9999 && inodo.mode <= 99999) {
		printfCUCA("       ");
	} else if (inodo.mode > 99999 && inodo.mode <= 999999) {
		printfCUCA("      ");
	} else if (inodo.mode > 999999 && inodo.mode <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.mode > 9999999 && inodo.mode <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.mode > 99999999 && inodo.mode <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.mode > 999999999 && inodo.mode <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.mode > 9999999999 && inodo.mode <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("                   TIEMPO DE ÚLTIMO ACCESO: %d", inodo.aTime);
	if (inodo.aTime >= 0 && inodo.aTime <= 9) {
		printfCUCA("           ");
	} else if (inodo.aTime > 9 && inodo.aTime <= 99) {
		printfCUCA("          ");
	} else if (inodo.aTime > 99 && inodo.aTime <= 999) {
		printfCUCA("         ");
	} else if (inodo.aTime > 999 && inodo.aTime <= 9999) {
		printfCUCA("        ");
	} else if (inodo.aTime > 9999 && inodo.aTime <= 99999) {
		printfCUCA("       ");
	} else if (inodo.aTime > 99999 && inodo.aTime <= 999999) {
		printfCUCA("      ");
	} else if (inodo.aTime > 999999 && inodo.aTime <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.aTime > 9999999 && inodo.aTime <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.aTime > 99999999 && inodo.aTime <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.aTime > 999999999 && inodo.aTime <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.aTime > 9999999999 && inodo.aTime <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("  |\n");
	printfCUCA("| CANTIDAD DE BLOQUES: %d", inodo.blocks);
	if (inodo.blocks >= 0 && inodo.blocks <= 9) {
		printfCUCA("           ");
	} else if (inodo.blocks > 9 && inodo.blocks <= 99) {
		printfCUCA("          ");
	} else if (inodo.blocks > 99 && inodo.blocks <= 999) {
		printfCUCA("         ");
	} else if (inodo.blocks > 999 && inodo.blocks <= 9999) {
		printfCUCA("        ");
	} else if (inodo.blocks > 9999 && inodo.blocks <= 99999) {
		printfCUCA("       ");
	} else if (inodo.blocks > 99999 && inodo.blocks <= 999999) {
		printfCUCA("      ");
	} else if (inodo.blocks > 999999 && inodo.blocks <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.blocks > 9999999 && inodo.blocks <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.blocks > 99999999 && inodo.blocks <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.blocks > 999999999 && inodo.blocks <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.blocks > 9999999999 && inodo.blocks <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("    TIEMPO DE CREACIÓN: %d", inodo.cTime);
	if (inodo.cTime >= 0 && inodo.cTime <= 9) {
		printfCUCA("           ");
	} else if (inodo.cTime > 9 && inodo.cTime <= 99) {
		printfCUCA("          ");
	} else if (inodo.cTime > 99 && inodo.cTime <= 999) {
		printfCUCA("         ");
	} else if (inodo.cTime > 999 && inodo.cTime <= 9999) {
		printfCUCA("        ");
	} else if (inodo.cTime > 9999 && inodo.cTime <= 99999) {
		printfCUCA("       ");
	} else if (inodo.cTime > 99999 && inodo.cTime <= 999999) {
		printfCUCA("      ");
	} else if (inodo.cTime > 999999 && inodo.cTime <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.cTime > 9999999 && inodo.cTime <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.cTime > 99999999 && inodo.cTime <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.cTime > 999999999 && inodo.cTime <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.cTime > 9999999999 && inodo.cTime <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("       |\n");
	printfCUCA("| TAMAÑO: %d", inodo.size);
	if (inodo.size >= 0 && inodo.size <= 9) {
		printfCUCA("           ");
	} else if (inodo.size > 9 && inodo.size <= 99) {
		printfCUCA("          ");
	} else if (inodo.size > 99 && inodo.size <= 999) {
		printfCUCA("         ");
	} else if (inodo.size > 999 && inodo.size <= 9999) {
		printfCUCA("        ");
	} else if (inodo.size > 9999 && inodo.size <= 99999) {
		printfCUCA("       ");
	} else if (inodo.size > 99999 && inodo.size <= 999999) {
		printfCUCA("      ");
	} else if (inodo.size > 999999 && inodo.size <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.size > 9999999 && inodo.size <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.size > 99999999 && inodo.size <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.size > 999999999 && inodo.size <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.size > 9999999999 && inodo.size <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("                 TIEMPO DE MODIFICACIÓN: %d", inodo.mTime);
	if (inodo.mTime >= 0 && inodo.mTime <= 9) {
		printfCUCA("           ");
	} else if (inodo.mTime > 9 && inodo.mTime <= 99) {
		printfCUCA("          ");
	} else if (inodo.mTime > 99 && inodo.mTime <= 999) {
		printfCUCA("         ");
	} else if (inodo.mTime > 999 && inodo.mTime <= 9999) {
		printfCUCA("        ");
	} else if (inodo.mTime > 9999 && inodo.mTime <= 99999) {
		printfCUCA("       ");
	} else if (inodo.mTime > 99999 && inodo.mTime <= 999999) {
		printfCUCA("      ");
	} else if (inodo.mTime > 999999 && inodo.mTime <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.mTime > 9999999 && inodo.mTime <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.mTime > 99999999 && inodo.mTime <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.mTime > 999999999 && inodo.mTime <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.mTime > 9999999999 && inodo.mTime <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("   |\n");
	printfCUCA("| GID: %d", inodo.GID);
	if (inodo.GID >= 0 && inodo.GID <= 9) {
		printfCUCA("           ");
	} else if (inodo.GID > 9 && inodo.GID <= 99) {
		printfCUCA("          ");
	} else if (inodo.GID > 99 && inodo.GID <= 999) {
		printfCUCA("         ");
	} else if (inodo.GID > 999 && inodo.GID <= 9999) {
		printfCUCA("        ");
	} else if (inodo.GID > 9999 && inodo.GID <= 99999) {
		printfCUCA("       ");
	} else if (inodo.GID > 99999 && inodo.GID <= 999999) {
		printfCUCA("      ");
	} else if (inodo.GID > 999999 && inodo.GID <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.GID > 9999999 && inodo.GID <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.GID > 99999999 && inodo.GID <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.GID > 999999999 && inodo.GID <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.GID > 9999999999 && inodo.GID <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("                    TIEMPO DE ELIMINACIÓN: %d", inodo.dTime);
	if (inodo.dTime >= 0 && inodo.dTime <= 9) {
		printfCUCA("           ");
	} else if (inodo.dTime > 9 && inodo.dTime <= 99) {
		printfCUCA("          ");
	} else if (inodo.dTime > 99 && inodo.dTime <= 999) {
		printfCUCA("         ");
	} else if (inodo.dTime > 999 && inodo.dTime <= 9999) {
		printfCUCA("        ");
	} else if (inodo.dTime > 9999 && inodo.dTime <= 99999) {
		printfCUCA("       ");
	} else if (inodo.dTime > 99999 && inodo.dTime <= 999999) {
		printfCUCA("      ");
	} else if (inodo.dTime > 999999 && inodo.dTime <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.dTime > 9999999 && inodo.dTime <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.dTime > 99999999 && inodo.dTime <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.dTime > 999999999 && inodo.dTime <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.dTime > 9999999999 && inodo.dTime <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("    |\n");
	printfCUCA("| REFERENCIAS: %d", inodo.linksCount);
	if (inodo.linksCount >= 0 && inodo.linksCount <= 9) {
		printfCUCA("           ");
	} else if (inodo.linksCount > 9 && inodo.linksCount <= 99) {
		printfCUCA("          ");
	} else if (inodo.linksCount > 99 && inodo.linksCount <= 999) {
		printfCUCA("         ");
	} else if (inodo.linksCount > 999 && inodo.linksCount <= 9999) {
		printfCUCA("        ");
	} else if (inodo.linksCount > 9999 && inodo.linksCount <= 99999) {
		printfCUCA("       ");
	} else if (inodo.linksCount > 99999 && inodo.linksCount <= 999999) {
		printfCUCA("      ");
	} else if (inodo.linksCount > 999999 && inodo.linksCount <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.linksCount > 9999999 && inodo.linksCount <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.linksCount > 99999999 && inodo.linksCount <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.linksCount > 999999999 && inodo.linksCount <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.linksCount > 9999999999 && inodo.linksCount <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("            FLAGS: %d", inodo.flags);
	if (inodo.flags >= 0 && inodo.flags <= 9) {
		printfCUCA("           ");
	} else if (inodo.flags > 9 && inodo.flags <= 99) {
		printfCUCA("          ");
	} else if (inodo.flags > 99 && inodo.flags <= 999) {
		printfCUCA("         ");
	} else if (inodo.flags > 999 && inodo.flags <= 9999) {
		printfCUCA("        ");
	} else if (inodo.flags > 9999 && inodo.flags <= 99999) {
		printfCUCA("       ");
	} else if (inodo.flags > 99999 && inodo.flags <= 999999) {
		printfCUCA("      ");
	} else if (inodo.flags > 999999 && inodo.flags <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.flags > 9999999 && inodo.flags <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.flags > 99999999 && inodo.flags <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.flags > 999999999 && inodo.flags <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.flags > 9999999999 && inodo.flags <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("                    |\n");
	printfCUCA("| FILE ACL: %d", inodo.fileACL);
	if (inodo.fileACL >= 0 && inodo.fileACL <= 9) {
		printfCUCA("           ");
	} else if (inodo.fileACL > 9 && inodo.fileACL <= 99) {
		printfCUCA("          ");
	} else if (inodo.fileACL > 99 && inodo.fileACL <= 999) {
		printfCUCA("         ");
	} else if (inodo.fileACL > 999 && inodo.fileACL <= 9999) {
		printfCUCA("        ");
	} else if (inodo.fileACL > 9999 && inodo.fileACL <= 99999) {
		printfCUCA("       ");
	} else if (inodo.fileACL > 99999 && inodo.fileACL <= 999999) {
		printfCUCA("      ");
	} else if (inodo.fileACL > 999999 && inodo.fileACL <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.fileACL > 9999999 && inodo.fileACL <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.fileACL > 99999999 && inodo.fileACL <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.fileACL > 999999999 && inodo.fileACL <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.fileACL > 9999999999 && inodo.fileACL <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("               OSD1: %d", inodo.osd1);
	if (inodo.osd1 >= 0 && inodo.osd1 <= 9) {
		printfCUCA("           ");
	} else if (inodo.osd1 > 9 && inodo.osd1 <= 99) {
		printfCUCA("          ");
	} else if (inodo.osd1 > 99 && inodo.osd1 <= 999) {
		printfCUCA("         ");
	} else if (inodo.osd1 > 999 && inodo.osd1 <= 9999) {
		printfCUCA("        ");
	} else if (inodo.osd1 > 9999 && inodo.osd1 <= 99999) {
		printfCUCA("       ");
	} else if (inodo.osd1 > 99999 && inodo.osd1 <= 999999) {
		printfCUCA("      ");
	} else if (inodo.osd1 > 999999 && inodo.osd1 <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.osd1 > 9999999 && inodo.osd1 <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.osd1 > 99999999 && inodo.osd1 <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.osd1 > 999999999 && inodo.osd1 <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.osd1 > 9999999999 && inodo.osd1 <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("                     |\n");
	printfCUCA("| DIRACL: %d", inodo.dirACL);
	if (inodo.dirACL >= 0 && inodo.dirACL <= 9) {
		printfCUCA("           ");
	} else if (inodo.dirACL > 9 && inodo.dirACL <= 99) {
		printfCUCA("          ");
	} else if (inodo.dirACL > 99 && inodo.dirACL <= 999) {
		printfCUCA("         ");
	} else if (inodo.dirACL > 999 && inodo.dirACL <= 9999) {
		printfCUCA("        ");
	} else if (inodo.dirACL > 9999 && inodo.dirACL <= 99999) {
		printfCUCA("       ");
	} else if (inodo.dirACL > 99999 && inodo.dirACL <= 999999) {
		printfCUCA("      ");
	} else if (inodo.dirACL > 999999 && inodo.dirACL <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.dirACL > 9999999 && inodo.dirACL <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.dirACL > 99999999 && inodo.dirACL <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.dirACL > 999999999 && inodo.dirACL <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.dirACL > 9999999999 && inodo.dirACL <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("                 ÚLTIMO FRAGMENTO: %d", inodo.fAddr);
	if (inodo.fAddr >= 0 && inodo.fAddr <= 9) {
		printfCUCA("           ");
	} else if (inodo.fAddr > 9 && inodo.fAddr <= 99) {
		printfCUCA("          ");
	} else if (inodo.fAddr > 99 && inodo.fAddr <= 999) {
		printfCUCA("         ");
	} else if (inodo.fAddr > 999 && inodo.fAddr <= 9999) {
		printfCUCA("        ");
	} else if (inodo.fAddr > 9999 && inodo.fAddr <= 99999) {
		printfCUCA("       ");
	} else if (inodo.fAddr > 99999 && inodo.fAddr <= 999999) {
		printfCUCA("      ");
	} else if (inodo.fAddr > 999999 && inodo.fAddr <= 9999999) {
		printfCUCA("     ");
	} else if (inodo.fAddr > 9999999 && inodo.fAddr <= 99999999) {
		printfCUCA("    ");
	} else if (inodo.fAddr > 99999999 && inodo.fAddr <= 999999999) {
		printfCUCA("   ");
	} else if (inodo.fAddr > 999999999 && inodo.fAddr <= 9999999999) {
		printfCUCA("  ");
	} else if (inodo.fAddr > 9999999999 && inodo.fAddr <= 99999999999) {
		printfCUCA(" ");
	}
	printfCUCA("         |\n");
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("| PUNTEROS DIRECTOS :      0 --> %d", (inodo.block)[0]);
	if ((inodo.block)[0] >= 0 && (inodo.block)[0] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[0] > 9 && (inodo.block)[0] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[0] > 99 && (inodo.block)[0] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[0] > 999 && (inodo.block)[0] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[0] > 9999 && (inodo.block)[0] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     4 --> %d", (inodo.block)[4]);
	if ((inodo.block)[4] >= 0 && (inodo.block)[4] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[4] > 9 && (inodo.block)[4] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[4] > 99 && (inodo.block)[4] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[4] > 999 && (inodo.block)[4] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[4] > 9999 && (inodo.block)[4] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     8 --> %d", (inodo.block)[8]);
	if ((inodo.block)[8] >= 0 && (inodo.block)[8] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[8] > 9 && (inodo.block)[8] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[8] > 99 && (inodo.block)[8] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[8] > 999 && (inodo.block)[8] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[8] > 9999 && (inodo.block)[8] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     |\n");

	printfCUCA("|                          1 --> %d", (inodo.block)[1]);
	if ((inodo.block)[1] >= 0 && (inodo.block)[1] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[1] > 9 && (inodo.block)[1] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[1] > 99 && (inodo.block)[1] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[1] > 999 && (inodo.block)[1] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[1] > 9999 && (inodo.block)[1] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     5 --> %d", (inodo.block)[5]);
	if ((inodo.block)[5] >= 0 && (inodo.block)[6] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[5] > 9 && (inodo.block)[5] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[5] > 99 && (inodo.block)[5] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[5] > 999 && (inodo.block)[5] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[5] > 9999 && (inodo.block)[5] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     9 --> %i", (inodo.block)[9]);
	if ((inodo.block)[9] >= 0 && (inodo.block)[9] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[9] > 9 && (inodo.block)[9] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[9] > 99 && (inodo.block)[9] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[9] > 999 && (inodo.block)[9] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[9] > 9999 && (inodo.block)[9] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     |\n");

	printfCUCA("|                          2 --> %d", (inodo.block)[2]);
	if ((inodo.block)[2] >= 0 && (inodo.block)[2] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[2] > 9 && (inodo.block)[2] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[2] > 99 && (inodo.block)[2] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[2] > 999 && (inodo.block)[2] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[2] > 9999 && (inodo.block)[2] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     6 --> %d", (inodo.block)[6]);
	if ((inodo.block)[6] >= 0 && (inodo.block)[6] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[6] > 9 && (inodo.block)[6] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[6] > 99 && (inodo.block)[6] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[6] > 999 && (inodo.block)[6] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[6] > 9999 && (inodo.block)[6] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("    10 --> %i", (inodo.block)[10]);
	if ((inodo.block)[10] >= 0 && (inodo.block)[10] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[10] > 9 && (inodo.block)[10] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[10] > 99 && (inodo.block)[10] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[10] > 999 && (inodo.block)[10] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[10] > 9999 && (inodo.block)[10] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     |\n");

	printfCUCA("|                          3 --> %d", (inodo.block)[3]);
	if ((inodo.block)[3] >= 0 && (inodo.block)[3] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[3] > 9 && (inodo.block)[3] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[3] > 99 && (inodo.block)[3] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[3] > 999 && (inodo.block)[3] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[3] > 9999 && (inodo.block)[3] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     7 --> %d", (inodo.block)[7]);
	if ((inodo.block)[7] >= 0 && (inodo.block)[7] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[7] > 9 && (inodo.block)[7] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[7] > 99 && (inodo.block)[7] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[7] > 999 && (inodo.block)[7] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[7] > 9999 && (inodo.block)[7] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("    11 --> %i", (inodo.block)[11]);
	if ((inodo.block)[11] >= 0 && (inodo.block)[11] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[11] > 9 && (inodo.block)[11] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[11] > 99 && (inodo.block)[11] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[11] > 999 && (inodo.block)[11] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[11] > 9999 && (inodo.block)[11] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("     |\n");

	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("| PUNTERO DE INDIRECCIÓN SIMPLE --> %d", (inodo.block)[12]);
	if ((inodo.block)[12] >= 0 && (inodo.block)[12] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[12] > 9 && (inodo.block)[12] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[12] > 99 && (inodo.block)[12] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[12] > 999 && (inodo.block)[12] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[12] > 9999 && (inodo.block)[12] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("                                    |\n");

	if (inodo.block[12] != 0) {
		uint32_t *puntIndSimple = (uint32_t*) leerBloqueGlobal(inodo.block[12]);
		uint32_t i;
		uint32_t l = 0;
		uint8_t primeraPagina = 1;
		uint32_t k = 0;
		for (i = 0; (i < 256) && (puntIndSimple[i] != 0); i++) {
			if ((i != 255) && (puntIndSimple[i] == puntIndSimple[i + 1] - 1)) {
				k++;
			} else {
				if (primeraPagina) {
					primeraPagina = 0;
					printfCUCA("| --> Punteros directos: %d al %d --> (%d .. %d)", l, k, puntIndSimple[l], puntIndSimple[k]);
					if (l >= 0 && l <= 9) {
						printfCUCA("     ");
					} else if (l > 9 && l <= 99) {
						printfCUCA("    ");
					} else if (l > 99 && l <= 999) {
						printfCUCA("   ");
					} else if (l > 999 && l <= 9999) {
						printfCUCA("  ");
					} else if (l > 9999 && l <= 99999) {
						printfCUCA(" ");
					}
					if (k >= 0 && k <= 9) {
						printfCUCA("     ");
					} else if (k > 9 && k <= 99) {
						printfCUCA("    ");
					} else if (k > 99 && k <= 999) {
						printfCUCA("   ");
					} else if (k > 999 && k <= 9999) {
						printfCUCA("  ");
					} else if (k > 9999 && k <= 99999) {
						printfCUCA(" ");
					}
					if (puntIndSimple[l] >= 0 && puntIndSimple[l] <= 9) {
						printfCUCA("     ");
					} else if (puntIndSimple[l] > 9 && puntIndSimple[l] <= 99) {
						printfCUCA("    ");
					} else if (puntIndSimple[l] > 99 && puntIndSimple[l] <= 999) {
						printfCUCA("   ");
					} else if (puntIndSimple[l] > 999 && puntIndSimple[l] <= 9999) {
						printfCUCA("  ");
					} else if (puntIndSimple[l] > 9999 && puntIndSimple[l] <= 99999) {
						printfCUCA(" ");
					}
					if (puntIndSimple[k] >= 0 && puntIndSimple[k] <= 9) {
						printfCUCA("     ");
					} else if (puntIndSimple[k] > 9 && puntIndSimple[k] <= 99) {
						printfCUCA("    ");
					} else if (puntIndSimple[k] > 99 && puntIndSimple[k] <= 999) {
						printfCUCA("   ");
					} else if (puntIndSimple[k] > 999 && puntIndSimple[k] <= 9999) {
						printfCUCA("  ");
					} else if (puntIndSimple[k] > 9999 && puntIndSimple[k] <= 99999) {
						printfCUCA(" ");
					}
					printfCUCA("              |\n");
					k = i + 1;
					l = i + 1;
				} else {
					printfCUCA("|                        %d al %d --> (%d .. %d)", l, k, puntIndSimple[l], puntIndSimple[k]);
					if (l >= 0 && l <= 9) {
						printfCUCA("     ");
					} else if (l > 9 && l <= 99) {
						printfCUCA("    ");
					} else if (l > 99 && l <= 999) {
						printfCUCA("   ");
					} else if (l > 999 && l <= 9999) {
						printfCUCA("  ");
					} else if (l > 9999 && l <= 99999) {
						printfCUCA(" ");
					}
					if (k >= 0 && k <= 9) {
						printfCUCA("     ");
					} else if (k > 9 && k <= 99) {
						printfCUCA("    ");
					} else if (k > 99 && k <= 999) {
						printfCUCA("   ");
					} else if (k > 999 && k <= 9999) {
						printfCUCA("  ");
					} else if (k > 9999 && k <= 99999) {
						printfCUCA(" ");
					}
					if (puntIndSimple[l] >= 0 && puntIndSimple[l] <= 9) {
						printfCUCA("     ");
					} else if (puntIndSimple[l] > 9 && puntIndSimple[l] <= 99) {
						printfCUCA("    ");
					} else if (puntIndSimple[l] > 99 && puntIndSimple[l] <= 999) {
						printfCUCA("   ");
					} else if (puntIndSimple[l] > 999 && puntIndSimple[l] <= 9999) {
						printfCUCA("  ");
					} else if (puntIndSimple[l] > 9999 && puntIndSimple[l] <= 99999) {
						printfCUCA(" ");
					}
					if (puntIndSimple[k] >= 0 && puntIndSimple[k] <= 9) {
						printfCUCA("     ");
					} else if (puntIndSimple[k] > 9 && puntIndSimple[k] <= 99) {
						printfCUCA("    ");
					} else if (puntIndSimple[k] > 99 && puntIndSimple[k] <= 999) {
						printfCUCA("   ");
					} else if (puntIndSimple[k] > 999 && puntIndSimple[k] <= 9999) {
						printfCUCA("  ");
					} else if (puntIndSimple[k] > 9999 && puntIndSimple[k] <= 99999) {
						printfCUCA(" ");
					}
					printfCUCA("              |\n");
					k = i + 1;
					l = i + 1;
				}
			}
		}
		free(puntIndSimple);
	}
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("| PUNTERO DE INDIRECCIÓN DOBLE --> %d", (inodo.block)[13]);
	if ((inodo.block)[13] >= 0 && (inodo.block)[13] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[13] > 9 && (inodo.block)[13] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[13] > 99 && (inodo.block)[13] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[13] > 999 && (inodo.block)[13] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[13] > 9999 && (inodo.block)[13] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("                                     |\n");
	if (inodo.block[13] != 0) {
		uint32_t *puntIndDoble = (uint32_t*) leerBloqueGlobal(inodo.block[13]);
		uint32_t z;
		for (z = 0; (z < 256) && (puntIndDoble[z] != 0); z++) {
			printfCUCA("|                                                                             |\n");
			printfCUCA("| --> %dº puntero de indirección simple: %d", z, puntIndDoble[z]);
			if (z >= 0 && z <= 9) {
				printfCUCA("     ");
			} else if (z > 9 && z <= 99) {
				printfCUCA("    ");
			} else if (z > 99 && z <= 999) {
				printfCUCA("   ");
			} else if (z > 999 && z <= 9999) {
				printfCUCA("  ");
			} else if (z > 9999 && z <= 99999) {
				printfCUCA(" ");
			}
			if (puntIndDoble[z] >= 0 && puntIndDoble[z] <= 9) {
				printfCUCA("     ");
			} else if (puntIndDoble[z] > 9 && puntIndDoble[z] <= 99) {
				printfCUCA("    ");
			} else if (puntIndDoble[z] > 99 && puntIndDoble[z] <= 999) {
				printfCUCA("   ");
			} else if (puntIndDoble[z] > 999 && puntIndDoble[z] <= 9999) {
				printfCUCA("  ");
			} else if (puntIndDoble[z] > 9999 && puntIndDoble[z] <= 99999) {
				printfCUCA(" ");
			}
			printfCUCA("                           |\n");
			uint32_t *puntIndSimple = (uint32_t*) leerBloqueGlobal(puntIndDoble[z]);
			uint32_t i;
			uint32_t l = 0;
			uint8_t primeraPagina = 1;
			uint32_t k = 0;
			for (i = 0; (i < 256) && (puntIndSimple[i] != 0); i++) {
				if ((i != 255) && (puntIndSimple[i] == puntIndSimple[i + 1] - 1)) {
					k++;
				} else {
					if (primeraPagina) {
						primeraPagina = 0;
						printfCUCA("|     --> Punteros directos: %d al %d --> (%d .. %d)", l, k, puntIndSimple[l], puntIndSimple[k]);
						if (l >= 0 && l <= 9) {
							printfCUCA("     ");
						} else if (l > 9 && l <= 99) {
							printfCUCA("    ");
						} else if (l > 99 && l <= 999) {
							printfCUCA("   ");
						} else if (l > 999 && l <= 9999) {
							printfCUCA("  ");
						} else if (l > 9999 && l <= 99999) {
							printfCUCA(" ");
						}
						if (k >= 0 && k <= 9) {
							printfCUCA("     ");
						} else if (k > 9 && k <= 99) {
							printfCUCA("    ");
						} else if (k > 99 && k <= 999) {
							printfCUCA("   ");
						} else if (k > 999 && k <= 9999) {
							printfCUCA("  ");
						} else if (k > 9999 && k <= 99999) {
							printfCUCA(" ");
						}
						if (puntIndSimple[l] >= 0 && puntIndSimple[l] <= 9) {
							printfCUCA("     ");
						} else if (puntIndSimple[l] > 9 && puntIndSimple[l] <= 99) {
							printfCUCA("    ");
						} else if (puntIndSimple[l] > 99 && puntIndSimple[l] <= 999) {
							printfCUCA("   ");
						} else if (puntIndSimple[l] > 999 && puntIndSimple[l] <= 9999) {
							printfCUCA("  ");
						} else if (puntIndSimple[l] > 9999 && puntIndSimple[l] <= 99999) {
							printfCUCA(" ");
						}
						if (puntIndSimple[k] >= 0 && puntIndSimple[k] <= 9) {
							printfCUCA("     ");
						} else if (puntIndSimple[k] > 9 && puntIndSimple[k] <= 99) {
							printfCUCA("    ");
						} else if (puntIndSimple[k] > 99 && puntIndSimple[k] <= 999) {
							printfCUCA("   ");
						} else if (puntIndSimple[k] > 999 && puntIndSimple[k] <= 9999) {
							printfCUCA("  ");
						} else if (puntIndSimple[k] > 9999 && puntIndSimple[k] <= 99999) {
							printfCUCA(" ");
						}
						printfCUCA("          |\n");
						k = i + 1;
						l = i + 1;
					} else {
						printfCUCA("|                            %d al %d --> (%d .. %d)", l, k, puntIndSimple[l], puntIndSimple[k]);
						if (l >= 0 && l <= 9) {
							printfCUCA("     ");
						} else if (l > 9 && l <= 99) {
							printfCUCA("    ");
						} else if (l > 99 && l <= 999) {
							printfCUCA("   ");
						} else if (l > 999 && l <= 9999) {
							printfCUCA("  ");
						} else if (l > 9999 && l <= 99999) {
							printfCUCA(" ");
						}
						if (k >= 0 && k <= 9) {
							printfCUCA("     ");
						} else if (k > 9 && k <= 99) {
							printfCUCA("    ");
						} else if (k > 99 && k <= 999) {
							printfCUCA("   ");
						} else if (k > 999 && k <= 9999) {
							printfCUCA("  ");
						} else if (k > 9999 && k <= 99999) {
							printfCUCA(" ");
						}
						if (puntIndSimple[l] >= 0 && puntIndSimple[l] <= 9) {
							printfCUCA("     ");
						} else if (puntIndSimple[l] > 9 && puntIndSimple[l] <= 99) {
							printfCUCA("    ");
						} else if (puntIndSimple[l] > 99 && puntIndSimple[l] <= 999) {
							printfCUCA("   ");
						} else if (puntIndSimple[l] > 999 && puntIndSimple[l] <= 9999) {
							printfCUCA("  ");
						} else if (puntIndSimple[l] > 9999 && puntIndSimple[l] <= 99999) {
							printfCUCA(" ");
						}
						if (puntIndSimple[k] >= 0 && puntIndSimple[k] <= 9) {
							printfCUCA("     ");
						} else if (puntIndSimple[k] > 9 && puntIndSimple[k] <= 99) {
							printfCUCA("    ");
						} else if (puntIndSimple[k] > 99 && puntIndSimple[k] <= 999) {
							printfCUCA("   ");
						} else if (puntIndSimple[k] > 999 && puntIndSimple[k] <= 9999) {
							printfCUCA("  ");
						} else if (puntIndSimple[k] > 9999 && puntIndSimple[k] <= 99999) {
							printfCUCA(" ");
						}
						printfCUCA("          |\n");
						k = i + 1;
						l = i + 1;
					}
				}
			}
			free(puntIndSimple);
		}
		free(puntIndDoble);
	}
	/*
	 if (inodo.block[13] != 0) {
	 uint32_t *puntIndDoble = (uint32_t*) leerBloqueGlobal(inodo.block[13]);
	 uint32_t i;
	 printfCUCA("  > PUNTEROS DE INDIRECCIÓN SIMPLE\n");
	 for (i = 0; (i < 256) && (puntIndDoble[i] != 0); i++) {
	 printfCUCA("  --> %d: [%d]\n", i, puntIndDoble[i]);
	 uint32_t j;
	 uint32_t *puntIndSimple = (uint32_t*) leerBloqueGlobal(puntIndDoble[i]);
	 printfCUCA("    > PUNTEROS DIRECTOS\n");
	 for (j = 0; (j < 256) && (puntIndSimple[j] != 0); j++) {
	 printfCUCA("    --> %d: [%d]\n", j, puntIndSimple[j]);
	 }
	 free(puntIndSimple);
	 }
	 free(puntIndDoble);
	 }
	 */
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("| PUNTERO DE INDIRECCIÓN TRIPLE --> %d", (inodo.block)[14]);
	if ((inodo.block)[14] >= 0 && (inodo.block)[14] <= 9) {
		printfCUCA("     ");
	} else if ((inodo.block)[14] > 9 && (inodo.block)[14] <= 99) {
		printfCUCA("    ");
	} else if ((inodo.block)[14] > 99 && (inodo.block)[14] <= 999) {
		printfCUCA("   ");
	} else if ((inodo.block)[14] > 999 && (inodo.block)[14] <= 9999) {
		printfCUCA("  ");
	} else if ((inodo.block)[14] > 9999 && (inodo.block)[14] <= 99999) {
		printfCUCA(" ");
	}
	printfCUCA("                                    |\n");

	if (inodo.block[14] != 0) {
		uint32_t *puntIndTriple = (uint32_t*) leerBloqueGlobal(inodo.block[14]);
		uint32_t x;
		for (x = 0; (x < 256) && (puntIndTriple[x] != 0); x++) {
			printfCUCA("|                                                                             |\n");
			printfCUCA("| --> %dº puntero de indirección doble: %d", x, puntIndTriple[x]);
			if (x >= 0 && x <= 9) {
				printfCUCA("     ");
			} else if (x > 9 && x <= 99) {
				printfCUCA("    ");
			} else if (x > 99 && x <= 999) {
				printfCUCA("   ");
			} else if (x > 999 && x <= 9999) {
				printfCUCA("  ");
			} else if (x > 9999 && x <= 99999) {
				printfCUCA(" ");
			}
			if (puntIndTriple[x] >= 0 && puntIndTriple[x] <= 9) {
				printfCUCA("     ");
			} else if (puntIndTriple[x] > 9 && puntIndTriple[x] <= 99) {
				printfCUCA("    ");
			} else if (puntIndTriple[x] > 99 && puntIndTriple[x] <= 999) {
				printfCUCA("   ");
			} else if (puntIndTriple[x] > 999 && puntIndTriple[x] <= 9999) {
				printfCUCA("  ");
			} else if (puntIndTriple[x] > 9999 && puntIndTriple[x] <= 99999) {
				printfCUCA(" ");
			}
			printfCUCA("                            |\n");
			uint32_t *puntIndDoble = (uint32_t*) leerBloqueGlobal(puntIndTriple[x]);
			uint32_t y;
			for (y = 0; (y < 256) && (puntIndDoble[y] != 0); y++) {
				printfCUCA("|     --> %dº puntero de indirección simple: %d", y, puntIndDoble[y]);
				if (y >= 0 && y <= 9) {
					printfCUCA("     ");
				} else if (y > 9 && y <= 99) {
					printfCUCA("    ");
				} else if (y > 99 && y <= 999) {
					printfCUCA("   ");
				} else if (y > 999 && y <= 9999) {
					printfCUCA("  ");
				} else if (y > 9999 && y <= 99999) {
					printfCUCA(" ");
				}
				if (puntIndDoble[y] >= 0 && puntIndDoble[y] <= 9) {
					printfCUCA("     ");
				} else if (puntIndDoble[y] > 9 && puntIndDoble[y] <= 99) {
					printfCUCA("    ");
				} else if (puntIndDoble[y] > 99 && puntIndDoble[y] <= 999) {
					printfCUCA("   ");
				} else if (puntIndDoble[y] > 999 && puntIndDoble[y] <= 9999) {
					printfCUCA("  ");
				} else if (puntIndDoble[y] > 9999 && puntIndDoble[y] <= 99999) {
					printfCUCA(" ");
				}
				printfCUCA("                       |\n");
				uint32_t *puntIndSimple = (uint32_t*) leerBloqueGlobal(puntIndDoble[y]);
				uint32_t i;
				uint32_t l = 0;
				uint8_t primeraPagina = 1;
				uint32_t k = 0;
				for (i = 0; (i < 256) && (puntIndSimple[i] != 0); i++) {
					if ((i != 255) && (puntIndSimple[i] == puntIndSimple[i + 1] - 1)) {
						k++;
					} else {
						if (primeraPagina) {
							primeraPagina = 0;
							printfCUCA("|             --> Punteros directos: %d al %d --> (%d .. %d)", l, k, puntIndSimple[l], puntIndSimple[k]);
							if (l >= 0 && l <= 9) {
								printfCUCA("     ");
							} else if (l > 9 && l <= 99) {
								printfCUCA("    ");
							} else if (l > 99 && l <= 999) {
								printfCUCA("   ");
							} else if (l > 999 && l <= 9999) {
								printfCUCA("  ");
							} else if (l > 9999 && l <= 99999) {
								printfCUCA(" ");
							}
							if (k >= 0 && k <= 9) {
								printfCUCA("     ");
							} else if (k > 9 && k <= 99) {
								printfCUCA("    ");
							} else if (k > 99 && k <= 999) {
								printfCUCA("   ");
							} else if (k > 999 && k <= 9999) {
								printfCUCA("  ");
							} else if (k > 9999 && k <= 99999) {
								printfCUCA(" ");
							}
							if (puntIndSimple[l] >= 0 && puntIndSimple[l] <= 9) {
								printfCUCA("     ");
							} else if (puntIndSimple[l] > 9 && puntIndSimple[l] <= 99) {
								printfCUCA("    ");
							} else if (puntIndSimple[l] > 99 && puntIndSimple[l] <= 999) {
								printfCUCA("   ");
							} else if (puntIndSimple[l] > 999 && puntIndSimple[l] <= 9999) {
								printfCUCA("  ");
							} else if (puntIndSimple[l] > 9999 && puntIndSimple[l] <= 99999) {
								printfCUCA(" ");
							}
							if (puntIndSimple[k] >= 0 && puntIndSimple[k] <= 9) {
								printfCUCA("     ");
							} else if (puntIndSimple[k] > 9 && puntIndSimple[k] <= 99) {
								printfCUCA("    ");
							} else if (puntIndSimple[k] > 99 && puntIndSimple[k] <= 999) {
								printfCUCA("   ");
							} else if (puntIndSimple[k] > 999 && puntIndSimple[k] <= 9999) {
								printfCUCA("  ");
							} else if (puntIndSimple[k] > 9999 && puntIndSimple[k] <= 99999) {
								printfCUCA(" ");
							}
							printfCUCA("  |\n");
							k = i + 1;
							l = i + 1;
						} else {
							printfCUCA("|                                    %d al %d --> (%d .. %d)", l, k, puntIndSimple[l], puntIndSimple[k]);
							if (l >= 0 && l <= 9) {
								printfCUCA("     ");
							} else if (l > 9 && l <= 99) {
								printfCUCA("    ");
							} else if (l > 99 && l <= 999) {
								printfCUCA("   ");
							} else if (l > 999 && l <= 9999) {
								printfCUCA("  ");
							} else if (l > 9999 && l <= 99999) {
								printfCUCA(" ");
							}
							if (k >= 0 && k <= 9) {
								printfCUCA("     ");
							} else if (k > 9 && k <= 99) {
								printfCUCA("    ");
							} else if (k > 99 && k <= 999) {
								printfCUCA("   ");
							} else if (k > 999 && k <= 9999) {
								printfCUCA("  ");
							} else if (k > 9999 && k <= 99999) {
								printfCUCA(" ");
							}
							if (puntIndSimple[l] >= 0 && puntIndSimple[l] <= 9) {
								printfCUCA("     ");
							} else if (puntIndSimple[l] > 9 && puntIndSimple[l] <= 99) {
								printfCUCA("    ");
							} else if (puntIndSimple[l] > 99 && puntIndSimple[l] <= 999) {
								printfCUCA("   ");
							} else if (puntIndSimple[l] > 999 && puntIndSimple[l] <= 9999) {
								printfCUCA("  ");
							} else if (puntIndSimple[l] > 9999 && puntIndSimple[l] <= 99999) {
								printfCUCA(" ");
							}
							if (puntIndSimple[k] >= 0 && puntIndSimple[k] <= 9) {
								printfCUCA("     ");
							} else if (puntIndSimple[k] > 9 && puntIndSimple[k] <= 99) {
								printfCUCA("    ");
							} else if (puntIndSimple[k] > 99 && puntIndSimple[k] <= 999) {
								printfCUCA("   ");
							} else if (puntIndSimple[k] > 999 && puntIndSimple[k] <= 9999) {
								printfCUCA("  ");
							} else if (puntIndSimple[k] > 9999 && puntIndSimple[k] <= 99999) {
								printfCUCA(" ");
							}
							printfCUCA("  |\n");
							k = i + 1;
							l = i + 1;
						}
					}
				}
				free(puntIndSimple);
			}
			free(puntIndDoble);
		}
		free(puntIndTriple);
	}

	/*
	 if (inodo.block[14] != 0) {
	 uint32_t *puntIndTriple = (uint32_t*) leerBloqueGlobal(inodo.block[14]);
	 uint32_t i;
	 printfCUCA("  > PUNTEROS DE INDIRECCIÓN DOBLE\n");
	 for (i = 0; (i < 256) && (puntIndTriple[i] != 0); i++) {
	 printfCUCA("  --> %d: [%d]\n", i, puntIndTriple[i]);
	 uint32_t j;
	 uint32_t *puntIndDoble = (uint32_t*) leerBloqueGlobal(puntIndTriple[i]);
	 printfCUCA("    > PUNTEROS DE INDIRECCIÓN SIMPLE\n");
	 for (j = 0; (j < 256) && (puntIndDoble[j] != 0); j++) {
	 printfCUCA("    --> %d: [%d]\n", j, puntIndDoble[j]);
	 uint32_t k;
	 uint32_t *puntIndSimple = (uint32_t*) leerBloqueGlobal(puntIndDoble[j]);
	 printfCUCA("      > PUNTEROS DIRECTOS\n");
	 for (k = 0; (k < 256) && (puntIndSimple[k] != 0); k++) {
	 printfCUCA("      --> %d: [%d]\n", k, puntIndSimple[k]);
	 }
	 free(puntIndSimple);
	 }
	 free(puntIndDoble);
	 }
	 free(puntIndTriple);
	 }
	 */
}

void imprimirContenidoInodo(inodeStructure_t inodo) {
	printfCUCA("===============================================================================\n");
	printfCUCA("                            > CONTENIDO DEL I-NODO <                           \n");
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> MODO: [%d]\n", inodo.mode);
	//printfCUCA("> UID: [%d]\n", inodo.UID);
	printfCUCA("> TAMAÑO: [%d]\n", inodo.size);
	printfCUCA("> TIEMPO DE ÚLTIMO ACCESO: [%d]\n", inodo.aTime);
	printfCUCA("> TIEMPO DE CREACIÓN: [%d]\n", inodo.cTime);
	printfCUCA("> TIEMPO DE MODIFICACIÓN: [%d]\n", inodo.mTime);
	printfCUCA("> TIEMPO DE ELIMINACIÓN: [%d]\n", inodo.dTime);
	//printfCUCA("> GID: [%d]\n", inodo.GID);
	printfCUCA("> CANTIDAD DE REFERENCIAS: [%d]\n", inodo.linksCount);
	printfCUCA("> CANTIDAD DE BLOQUES: [%d]\n", inodo.blocks);
	printfCUCA("> FLAGS: [%d]\n", inodo.flags);
	//printfCUCA("> OSD1: [%d]\n", inodo.osd1);
	printfCUCA("> VERSION: [%d]\n", inodo.generation);
	printfCUCA("> FILE ACL: [%d]\n", inodo.fileACL);
	printfCUCA("> DIRACL: [%d]\n", inodo.dirACL);
	printfCUCA("> ULTIMO FRAGMENTO: [%d]\n", inodo.fAddr);
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> PUNTEROS DIRECTOS:                 \n");
	printfCUCA("  --> 01: [%d]                           \n", (inodo.block)[0]);
	printfCUCA("  --> 02: [%d]                           \n", (inodo.block)[1]);
	printfCUCA("  --> 03: [%d]                           \n", (inodo.block)[2]);
	printfCUCA("  --> 04: [%d]                           \n", (inodo.block)[3]);
	printfCUCA("  --> 05: [%d]                           \n", (inodo.block)[4]);
	printfCUCA("  --> 06: [%d]                           \n", (inodo.block)[5]);
	printfCUCA("  --> 07: [%d]                           \n", (inodo.block)[6]);
	printfCUCA("  --> 08: [%d]                           \n", (inodo.block)[7]);
	printfCUCA("  --> 09: [%d]                           \n", (inodo.block)[8]);
	printfCUCA("  --> 10: [%d]                           \n", (inodo.block)[9]);
	printfCUCA("  --> 11: [%d]                           \n", (inodo.block)[10]);
	printfCUCA("  --> 12: [%d]                           \n", (inodo.block)[11]);
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> PUNTERO DE INDIRECCIÓN SIMPLE (%i) \n", (inodo.block)[12]);
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> PUNTERO DE INDIRECCIÓN DOBLE (%i) \n", (inodo.block)[13]);
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("> PUNTERO DE INDIRECCIÓN TRIPLE (%i) \n", (inodo.block)[14]);
}

inodeStructure_t* leerInodeTable(uint8_t numBlockGroup) {
	if (numBlockGroup < cantBlockGroups()) {
		uint32_t primerBloque = staticGroupDescriptorTable[numBlockGroup].inodeTable;
		uint64_t bytesInodeTable = inodeTableSize();
		char* contenido = (char*) malloc(bytesInodeTable);

		uint32_t cantBloques;
		div_t division = div(bytesInodeTable, staticSuperBlock.blockSize);
		if (division.rem != 0) {
			cantBloques = division.quot + 1;
		} else {
			cantBloques = division.quot;
		}

		uint32_t i;
		for (i = 0; i < cantBloques - 1; i++) {
			char* contenidoAux = leerBloqueGlobal(primerBloque + i);
			memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
			free(contenidoAux);
		}
		if (division.rem != 0) {
			char* contenidoAux = leerParteBloqueGlobal(primerBloque + i, 0, division.rem);
			memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, division.rem);
			free(contenidoAux);
		} else {
			char* contenidoAux = leerBloqueGlobal(primerBloque + i);
			memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoAux, staticSuperBlock.blockSize);
			free(contenidoAux);
		}
		inodeStructure_t* inodeTable = (inodeStructure_t*) malloc(bytesInodeTable);
		memcpy(inodeTable, contenido, bytesInodeTable);
		free(contenido);
		//TEST BEGIN
		//printfCUCA("------------------------------------------------------------\n");
		//printfCUCA("Contenido de la Inode Table del Block Group [%d]:\n", numBlockGroup);
		//for (i = 0; i < 20/*staticSuperBlock.inodesPerGroup*/; i++) {
		//printfCUCA("Inodo [%d]:\n", i);
		//imprimirContenidoInodo(inodeTable[i]);
		//}
		//TEST END
		return inodeTable;
	} else {
		return NULL;
	}
}

inodeStructure_t leerInodo(uint32_t numInodoAbsoluto) {
	printfCUCA("/////////////////////////////////// LEER INODO ////////////////////////////////////\n");
	uint8_t numBlockGroup = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).quot;
	printfCUCA("<leerInodo> numBlockGroup: %d\n", numBlockGroup);
	uint32_t numInodoRelativo = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).rem;
	printfCUCA("<leerInodo> numInodoRelativo: %d\n", numInodoRelativo);
	uint32_t numBloqueInicioTablaInodos = staticGroupDescriptorTable[numBlockGroup].inodeTable;
	printfCUCA("<leerInodo> numBloqueInicioTablaInodos: %d\n", numBloqueInicioTablaInodos);
	printfCUCA("<leerInodo> sizeof(inodeStructure_t) %d\n", sizeof(inodeStructure_t));
	uint32_t numBloqueDeInodo = div(numInodoRelativo, staticSuperBlock.blockSize / sizeof(inodeStructure_t)).quot;
	printfCUCA("<leerInodo> numBloqueDeInodo: %d\n", numBloqueDeInodo);
	uint32_t numBloqueAbsoluto = numBloqueInicioTablaInodos + numBloqueDeInodo;
	printfCUCA("<leerInodo> numBloqueAbsoluto: %d\n", numBloqueAbsoluto);
	char* contenidoBloque = leerBloqueGlobal(numBloqueAbsoluto);
	inodeStructure_t inodo;
	uint32_t desplazamientoDentroDeBloque = div(numInodoRelativo * sizeof(inodeStructure_t), staticSuperBlock.blockSize).rem;
	printfCUCA("<leerInodo> desplazamientoDentroDeBloque: %d\n", desplazamientoDentroDeBloque);
	memcpy(&inodo, contenidoBloque + desplazamientoDentroDeBloque, sizeof(inodeStructure_t));
	free(contenidoBloque);
	printfCUCA("///////////////////////////////////////////////////////////////////////////////////\n");
	return inodo;

	/*
	 uint8_t numBlockGroup = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).quot;
	 printf("<leerInodo> numBlockGroup %d\n", numBlockGroup);
	 uint32_t numInodoRelativo = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).rem;
	 printf("<leerInodo> numInodoRelativo %d\n", numInodoRelativo);
	 uint32_t numBloqueInicioTablaInodos = staticGroupDescriptorTable[numBlockGroup].inodeTable;
	 printf("<leerInodo> numBloqueInicioTablaInodos %d\n", numBloqueInicioTablaInodos);
	 printf("<leerInodo> staticSuperBlock.inodesPerGroup %d\n", staticSuperBlock.inodesPerGroup);
	 printf("<leerInodo> sizeof(inodeStructure_t) %d\n", sizeof(inodeStructure_t));
	 uint32_t cantBloquesTablaInodos = (staticSuperBlock.inodesPerGroup * sizeof(inodeStructure_t)) / staticSuperBlock.blockSize;
	 printf("<leerInodo> cantBloquesTablaInodos %d\n", cantBloquesTablaInodos);
	 if (((staticSuperBlock.inodesPerGroup * sizeof(inodeStructure_t)) % staticSuperBlock.blockSize) != 0) {
	 cantBloquesTablaInodos++;
	 printf("<leerInodo> cantBloquesTablaInodos %d\n", cantBloquesTablaInodos);
	 }
	 char* tablaInodos = malloc(cantBloquesTablaInodos * staticSuperBlock.blockSize);
	 uint32_t i;
	 for (i = 0; i < cantBloquesTablaInodos; i++) {
	 char* contenidoBloque = leerBloqueGlobal(numBloqueInicioTablaInodos + i);
	 memcpy(tablaInodos + (i * staticSuperBlock.blockSize), contenidoBloque, staticSuperBlock.blockSize);
	 free(contenidoBloque);
	 }
	 inodeStructure_t inodo;
	 memcpy(&inodo, tablaInodos + (numInodoRelativo * sizeof(inodeStructure_t)), sizeof(inodeStructure_t));
	 free(tablaInodos);
	 return inodo;
	 */
}

void escribirInodo(inodeStructure_t inodo, uint32_t numInodoAbsoluto) {
	printfCUCA("///////////////////////////////// ESCRIBIR INODO //////////////////////////////////\n");
	uint8_t numBlockGroup = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).quot;
	printfCUCA("<escribirInodo> numBlockGroup %d\n", numBlockGroup);
	uint32_t numInodoRelativo = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).rem;
	printfCUCA("<escribirInodo> numInodoRelativo %d\n", numInodoRelativo);
	uint32_t numBloqueInicioTablaInodos = staticGroupDescriptorTable[numBlockGroup].inodeTable;
	printfCUCA("<escribirInodo> numBloqueInicioTablaInodos %d\n", numBloqueInicioTablaInodos);
	printfCUCA("<escribirInodo> sizeof(inodeStructure_t) %d\n", sizeof(inodeStructure_t));
	uint32_t numBloqueDeInodo = div(numInodoRelativo, staticSuperBlock.blockSize / sizeof(inodeStructure_t)).quot;
	printfCUCA("<escribirInodo> numBloqueDeInodo %d\n", numBloqueDeInodo);
	uint32_t numBloqueAbsoluto = numBloqueInicioTablaInodos + numBloqueDeInodo;
	printfCUCA("<escribirInodo> numBloqueAbsoluto %d\n", numBlockGroup);
	char* contenidoBloque = leerBloqueGlobal(numBloqueAbsoluto);
	uint32_t desplazamientoDentroDeBloque = div(numInodoRelativo * sizeof(inodeStructure_t), staticSuperBlock.blockSize).rem;
	printfCUCA("<escribirInodo> desplazamientoDentroDeBloque: %d\n", desplazamientoDentroDeBloque);
	memcpy(contenidoBloque + desplazamientoDentroDeBloque, &inodo, sizeof(inodeStructure_t));
	escribirBloqueGlobal(numBloqueAbsoluto, contenidoBloque);
	free(contenidoBloque);
	printfCUCA("///////////////////////////////////////////////////////////////////////////////////\n");

	/*uint8_t numBlockGroup = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).quot;
	 printf("<escribirInodo> numBlockGroup %d\n", numBlockGroup);
	 uint32_t numInodoRelativo = div(numInodoAbsoluto, staticSuperBlock.inodesPerGroup).rem;
	 printf("<escribirInodo> numInodoRelativo %d\n", numInodoRelativo);
	 uint32_t numBloqueInicioTablaInodos = staticGroupDescriptorTable[numBlockGroup].inodeTable;
	 printf("<escribirInodo> numBloqueInicioTablaInodos %d\n", numBloqueInicioTablaInodos);
	 uint32_t cantBloquesTablaInodos = (staticSuperBlock.inodesPerGroup * sizeof(inodeStructure_t)) / staticSuperBlock.blockSize;
	 printf("<escribirInodo> cantBloquesTablaInodos %d\n", cantBloquesTablaInodos);
	 if (((staticSuperBlock.inodesPerGroup * sizeof(inodeStructure_t)) % staticSuperBlock.blockSize) != 0) {
	 cantBloquesTablaInodos++;
	 }
	 char* tablaInodos = malloc(cantBloquesTablaInodos * staticSuperBlock.blockSize);
	 uint32_t i;
	 for (i = 0; i < cantBloquesTablaInodos; i++) {
	 char* contenidoBloque = leerBloqueGlobal(numBloqueInicioTablaInodos + i);
	 memcpy(tablaInodos + (i * staticSuperBlock.blockSize), contenidoBloque, staticSuperBlock.blockSize);
	 free(contenidoBloque);
	 }
	 memcpy(tablaInodos + (numInodoRelativo * sizeof(inodeStructure_t)), &inodo, sizeof(inodeStructure_t));
	 for (i = 0; i < cantBloquesTablaInodos; i++) {
	 escribirBloqueGlobal(numBloqueInicioTablaInodos + i, tablaInodos + (i * staticSuperBlock.blockSize));
	 }
	 free(tablaInodos);*/
}

uint64_t inodeTableSize() {
	return staticSuperBlock.inodesPerGroup * sizeof(inodeStructure_t);
}

/*char* leerParteArchivo(inodeStructure_t inodo, uint64_t numBlockGroup, uint64_t blocksPerGroup, uint64_t byteDesde, uint64_t byteHasta){
 uint64_t primerBloqueArchivoALeer = div(byteDesde, staticSuperBlock.blockSize).quot;
 uint64_t desplazamientoPrimerBloqueArchivo = div(byteDesde, staticSuperBlock.blockSize).rem;
 uint64_t ultimoBloqueArchivoALeer = div(byteHasta, staticSuperBlock.blockSize).quot;
 uint64_t desplazamientoUltimoBloqueArchivo = div(byteHasta, staticSuperBlock.blockSize).rem;
 char* contenido = NULL;//(char*) malloc(byteHasta - byteDesde + 1);

 if(primerBloqueArchivoALeer == ultimoBloqueArchivoALeer){
 if(primerBloqueArchivoALeer < 13){
 //EL INODO DIRECCIONA DIRECTAMENTE AL BLOQUE
 contenido = leerParteBloqueLocal(numBlockGroup, blocksPerGroup, inodo.block[primerBloqueArchivoALeer], desplazamientoPrimerBloqueArchivo, desplazamientoUltimoBloqueArchivo);
 }else if(primerBloqueArchivoALeer >= 13 && primerBloqueArchivoALeer < ((staticSuperBlock.blockSize / 4) + 13)){
 //EL INODO APUNTA A UN BLOQUE CON DIRECCIONES DE BLOQUE
 uint32_t* tablaBloques = obtenerTablaDeBloques(numBlockGroup, blocksPerGroup, inodo.block[13]);
 uint64_t numBloque = primerBloqueArchivoALeer - 13;
 contenido = leerParteBloqueLocal(numBlockGroup, blocksPerGroup, tablaBloques[numBloque], desplazamientoPrimerBloqueArchivo, desplazamientoUltimoBloqueArchivo);
 }else if(primerBloqueArchivoALeer >= ((staticSuperBlock.blockSize / 4) + 13) && primerBloqueArchivoALeer < ((staticSuperBlock.blockSize * staticSuperBlock.blockSize / 4) + (staticSuperBlock.blockSize / 4) + 13)){
 //EL INODO APUNTA A UN BLOQUE CON PUNTEROS A BLOQUES CON DIRECCIONES DE BLOQUE

 }
 }
 if(primerBloqueArchivoALeer < 13){
 //LOS PRIMEROS NUMEROS DE BLOQUE ESTAN EN EL INODO
 uint64_t i;
 for(i = primerBloqueArchivoALeer; i < 13 && i < ultimoBloqueArchivoALeer;)
 }else{
 //TENGO QUE LEER LAS TABLAS CORRESPONDIENTES
 }





 uint64_t cantBloquesCompletos = div(inodo.size, staticSuperBlock.blockSize).quot;
 uint64_t bytesUltimoBloque = div(inodo.size, staticSuperBlock.blockSize).rem;
 memset(contenido, '\0', inodo.size);
 uint64_t i;
 for(i = 0; i < 13 && i < cantBloquesCompletos; i++){
 char* contenidoBloque = leerBloqueLocal(numBlockGroup, blocksPerGroup, inodo.block[i]);
 memcpy(contenido + (i * staticSuperBlock.blockSize), contenidoBloque, staticSuperBlock.blockSize);
 free(contenidoBloque);
 }
 if(i == 13 && cantBloquesCompletos >= 13){
 uint32_t* tablaDeBloques = obtenerTablaDeBloques(numBlockGroup, blocksPerGroup, inodo.block[i]);
 uint64_t cantBloquesEnTabla = staticSuperBlock.blockSize / 4;
 for(; i < cantBloquesEnTabla && i < cantBloquesCompletos; i++){

 }
 }else if(i == 13 && cantBloquesCompletos < 13){

 }else{

 }
 }*/

uint32_t* obtenerTablaDeBloques(uint64_t numBlockGroup, uint64_t numBlock) {
	char* contenidoBloque = leerBloqueLocal(numBlockGroup, numBlock);
	uint32_t* tabla = NULL;
	if (contenidoBloque != NULL) {
		tabla = (uint32_t*) malloc(staticSuperBlock.blockSize);
		memset(tabla, '0', staticSuperBlock.blockSize);
		memcpy(tabla, contenidoBloque, staticSuperBlock.blockSize);
	}
	free(contenidoBloque);
	return tabla;
}

void encolarBloque(nodoBloque_t** colaBloquesFte, nodoBloque_t** colaBloquesFin, char bloque[staticSuperBlock.blockSize]) {
	nodoBloque_t* nue = (nodoBloque_t*) malloc(sizeof(nodoBloque_t));
	memcpy(nue->contenidoBloque, bloque, staticSuperBlock.blockSize);
	nue->sig = NULL;

	if (*colaBloquesFte == NULL) {
		*colaBloquesFte = nue;
	} else {
		(*colaBloquesFin)->sig = nue;
	}
	*colaBloquesFin = nue;
}

char* desencolarBloque(nodoBloque_t** colaBloquesFte, nodoBloque_t** colaBloquesFin) {
	char* contenidoBloque = (char*) malloc(staticSuperBlock.blockSize);
	memcpy(contenidoBloque, (*colaBloquesFte)->contenidoBloque, staticSuperBlock.blockSize);

	nodoBloque_t* aux = malloc(sizeof(nodoBloque_t));
	aux = *colaBloquesFte;
	*colaBloquesFte = (*colaBloquesFte)->sig;
	if (*colaBloquesFte == NULL) {
		*colaBloquesFin = NULL;
	}
	free(aux);
	return contenidoBloque;
}

uint64_t cantidadNodosBloques(nodoBloque_t* colaBloquesFte, nodoBloque_t* colaBloquesFin) {
	uint64_t i;
	nodoBloque_t* aux;
	for (i = 0, aux = colaBloquesFte; aux != NULL; aux = aux->sig, i++)
		;
	return i;
}
//----------------------------------------------------------------------------------------------------
//INDIRECCIONAMIENTOS
//----------------------------------------------------------------------------------------------------

uint64_t maxCantBloquesNivelN(uint8_t nivel) {
	return potencia(staticSuperBlock.blockSize / sizeof(uint32_t), nivel);
}

bool estaEntrePunterosDirectos(uint64_t numPuntero) {
//NUM PUNTERO SE REFIERE A UN NUMERO DE BLOQUE DE DATOS
	if (numPuntero >= 0 && numPuntero < 12) {
		return true;
	} else {
		return false;
	}
}

bool estaEntrePunterosIndirectosSimples(uint64_t numPuntero) {
//NUM PUNTERO SE REFIERE A UN NUMERO DE BLOQUE DE DATOS
	if (numPuntero >= 12 && numPuntero < 12 + maxCantBloquesNivelN(1)) {
		return true;
	} else {
		return false;
	}
}

bool estaEntrePunterosIndirectosDobles(uint64_t numPuntero) {
//NUM PUNTERO SE REFIERE A UN NUMERO DE BLOQUE DE DATOS
	if (numPuntero >= 12 + maxCantBloquesNivelN(1) && numPuntero < 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
		return true;
	} else {
		return false;
	}
}

bool estaEntrePunterosIndirectosTriples(uint64_t numPuntero) {
//NUM PUNTERO SE REFIERE A UN NUMERO DE BLOQUE DE DATOS
	if (numPuntero >= 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2) && numPuntero < 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2) + maxCantBloquesNivelN(3)) {
		return true;
	} else {
		return false;
	}
}

/*uint64_t maxCantBloquesIndirectosSimples() {
 return staticSuperBlock.blockSize / sizeof(uint32_t);
 }

 uint64_t maxCantBloquesIndirectosDobles() {
 return staticSuperBlock.blockSize * staticSuperBlock.blockSize / sizeof(uint32_t);
 }

 uint64_t maxCantBloquesIndirectosTriples() {
 return staticSuperBlock.blockSize * staticSuperBlock.blockSize * staticSuperBlock.blockSize / sizeof(uint32_t);
 }*/

char* leerNBloquesNivel0(uint8_t blockGroup, uint32_t* puntDir, off_t byteOffset, size_t sizeBytes) {
//printfCUCA("Leo los direccionamientos directos.\n");
	char* contenido = NULL;
//printfCUCA("Tengo que leer [%d] bytes desde el byte [%d].\n", (uint32_t) sizeBytes, (uint32_t) byteOffset);
	if (sizeBytes > 0) {
		uint64_t byteFin = byteOffset + sizeBytes;
		div_t divInicio = div(byteOffset, staticSuperBlock.blockSize);
		uint16_t bloqueInicio = divInicio.quot;
		//printfCUCA("Tengo que leer el a partir del bloque [%d] con un offset de [%d].\n", bloqueInicio, divInicio.rem);
		div_t divFin = div(byteFin, staticSuperBlock.blockSize);
		uint16_t bloqueFin = divFin.quot;
		off_t offsetFinal = divFin.rem;
		//printfCUCA("Hasta el bloque [%d] con un offset de [%d].\n", bloqueFin, (uint32_t) offsetFinal);
		//printfCUCA("Bloque inicio:[%d]\n", bloqueInicio);
		if (divFin.rem == 0 && divFin.quot > 0) {
			bloqueFin--;
			offsetFinal = staticSuperBlock.blockSize; //TODO revisar que esto sea realmente necesario
			//printfCUCA("Como el offset es 0 seteo el bloque final a [%d] y el offset a [%d].\n", bloqueFin, (uint32_t) offsetFinal);
		}
		uint16_t punteroActual;
		contenido = malloc(sizeBytes);

		if (bloqueInicio == bloqueFin) {
			//EL PRIMERO TAMBIEN ES EL ULTIMO
			//printfCUCA("El primer bloque tambien es el ultimo.\n");
			punteroActual = bloqueInicio;
			//printfCUCA("Leo el contenido del bloque.\n");
			char* contenidoBloque = leerBloqueGlobal(puntDir[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			memcpy(contenido, contenidoBloque + divInicio.rem, sizeBytes);
			//printfCUCA("El contenido necesario del bloque es:\n");
			//uint32_t i;
			//for(i = 0; i < sizeBytes; i++){
			//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, (uint32_t) contenido[i], (uint32_t) contenido[i]);
			//}
			free(contenidoBloque);
		} else {
			//EL PRIMERO NO ES EL ULTIMO
			//printfCUCA("El primer bloque no es el ultimo.\n");
			//LEO EL PRIMERO
			//printfCUCA("Leo el primer bloque.\n");
			off_t offsetGrabacion = 0;
			punteroActual = bloqueInicio;
			char* contenidoBloque = leerBloqueGlobal(puntDir[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			memcpy(contenido, contenidoBloque + divInicio.rem, staticSuperBlock.blockSize - divInicio.rem);
			//printfCUCA("El contenido necesario del bloque es:\n");
			//uint32_t i;
			//for(i = 0; i < staticSuperBlock.blockSize - divInicio.rem; i++){
			//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, (uint32_t) contenido[i], (uint32_t) contenido[i]);
			//}

			free(contenidoBloque);
			offsetGrabacion = staticSuperBlock.blockSize - divInicio.rem;
			punteroActual++;
			//LEO LOS DEL MEDIO
			//printfCUCA("Leo los punteros del medio.\n");
			//SI SOLO SON DOS NO VA A ENTRAR EN EL FOR
			for (; punteroActual < bloqueFin; punteroActual++, offsetGrabacion += staticSuperBlock.blockSize) {
				//printfCUCA("El offset de grabacion se setea a: [%d]\n", (int32_t) offsetGrabacion);
				contenidoBloque = leerBloqueGlobal(puntDir[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
				memcpy(contenido + offsetGrabacion, contenidoBloque, staticSuperBlock.blockSize);
				free(contenidoBloque);

			}

			//LEO EL DEL FINAL
			//printfCUCA("Leo el puntero final.\n");
			//EL PUNTERO ACTUAL ES EL PUNTERO FINAL
			contenidoBloque = leerBloqueGlobal(puntDir[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			//uint64_t j;
			//for(j = 0; j < offsetFinal;j++){
			//printfCUCA("contenido Bloque [%d]:[%d]:[%c]\n", (uint32_t) j ,(uint32_t) contenidoBloque[j],contenidoBloque[j]);
			//}
			//printfCUCA("offset final: [%d]\n", (uint32_t) offsetFinal);
			//printfCUCA("Numero de Bloque a leer: puntDir[%d] = [%d].\n", punteroActual, puntDir[punteroActual]);
			//printfCUCA("offset de grabacion: [%d]\n", (uint32_t) offsetGrabacion);
			memcpy(contenido + offsetGrabacion, contenidoBloque, offsetFinal);
			free(contenidoBloque);
		}
	}
	/*uint32_t i;
	 for (i = 0; i < sizeBytes; i++) {
	 printfCUCA("[%d]:[%d]:[%c].\n", i, contenido[i], contenido[i]);
	 }*/
	return contenido;
}

char* leerNBloquesNivel1(uint8_t blockGroup, uint32_t* puntInd, off_t byteOffset, size_t sizeBytes) {
//printfCUCA("Leo los direccionamientos indirectos.\n");
	char* contenido = NULL;
	if (sizeBytes > 0) {
		uint64_t byteFin = byteOffset + sizeBytes;
		//printfCUCA("Tengo que leer [%d] bytes desde el byte [%d].\n", (uint32_t) sizeBytes, (uint32_t) byteOffset);
		div_t divInicio = div(byteOffset, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize);
		uint16_t punteroIndInicio = divInicio.quot;
		//printfCUCA("Tengo que empezar por el puntero [%d].\n", punteroIndInicio);
		div_t divFin = div(byteFin, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize);
		uint16_t punteroIndFin = divFin.quot;
		//printfCUCA("Tengo que leer hasta el puntero [%d].\n", punteroIndFin);
		off_t offsetFinal = divFin.rem;
		if (divFin.rem == 0 && divFin.quot > 0) {
			punteroIndFin--;
			offsetFinal = maxCantBloquesNivelN(1) * staticSuperBlock.blockSize; //TODO revisar que esto sea realmente necesario
			//printfCUCA("Como el offset es 0 seteo el bloque final a [%d] y el offset a [%d].\n", punteroIndFin, (uint32_t) offsetFinal);
		}

		uint16_t punteroActual;
		contenido = malloc(sizeBytes);

		if (punteroIndInicio == punteroIndFin) {
			//EL PRIMERO TAMBIEN ES EL ULTIMO
			//printfCUCA("El primer puntero tambien es el ultimo.\n");
			punteroActual = punteroIndInicio;
			char* contenidoBloque = leerBloqueGlobal(puntInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			uint32_t* puntDir = malloc(staticSuperBlock.blockSize);
			memcpy(puntDir, contenidoBloque, staticSuperBlock.blockSize);
			//printfCUCA("El contenido del bloque de direcciones es:\n");
			//uint32_t i;
			//for(i = 0; i < staticSuperBlock.blockSize / sizeof(uint32_t); i++){
			//printfCUCA("Puntero [%d] = [%d].\n", i, puntDir[i]);
			//}
			free(contenidoBloque);
			//printfCUCA("Leo los direccionamientos directos del bloque.\n");
			char* contenidoAux = leerNBloquesNivel0(blockGroup, puntDir, divInicio.rem, sizeBytes);
			//printfCUCA("El resultado de la lectura es:\n");
			//for(i = 0; i < sizeBytes; i++){
			//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, (uint32_t) contenidoAux[i], (uint32_t) contenidoAux[i]);
			//}
			free(puntDir);
			memcpy(contenido, contenidoAux, sizeBytes);
			free(contenidoAux);
		} else {
			//EL PRIMERO NO ES EL ULTIMO
			//LEO EL PRIMERO
			off_t offsetGrabacion = 0;
			punteroActual = punteroIndInicio;
			char* contenidoBloque = leerBloqueGlobal(puntInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			uint32_t* puntDir = malloc(staticSuperBlock.blockSize);
			memcpy(puntDir, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			char* contenidoAux = leerNBloquesNivel0(blockGroup, puntDir, divInicio.rem, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) - divInicio.rem);
			free(puntDir);
			memcpy(contenido, contenidoAux, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) - divInicio.rem);
			free(contenidoAux);

			offsetGrabacion = (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) - divInicio.rem;
			punteroActual++;

			//LEO LOS DEL MEDIO
			//SI SOLO SON DOS NO VA A ENTRAR EN EL FOR
			for (; punteroActual < punteroIndFin; punteroActual++) {
				contenidoBloque = leerBloqueGlobal(puntInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
				puntDir = malloc(staticSuperBlock.blockSize);
				memcpy(puntDir, contenidoBloque, staticSuperBlock.blockSize);
				free(contenidoBloque);
				contenidoAux = leerNBloquesNivel0(blockGroup, puntDir, 0, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize));
				free(puntDir);
				memcpy(contenido + offsetGrabacion, contenidoAux, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize);
				free(contenidoAux);

				offsetGrabacion += maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
			}

			//LEO EL DEL FINAL
			//EL PUNTERO ACTUAL ES EL PUNTERO FINAL
			contenidoBloque = leerBloqueGlobal(puntInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			puntDir = malloc(staticSuperBlock.blockSize);
			memcpy(puntDir, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			contenidoAux = leerNBloquesNivel0(blockGroup, puntDir, 0, offsetFinal);
			free(puntDir);
			memcpy(contenido + offsetGrabacion, contenidoAux, offsetFinal);
			free(contenidoAux);
		}
	}
	return contenido;
}

char* leerNBloquesNivel2(uint8_t blockGroup, uint32_t* puntBiInd, off_t byteOffset, size_t sizeBytes) {
	char* contenido = NULL;
	if (sizeBytes > 0) {
		printfCUCA("<leerNBloquesNivel2> byteOffset: %d\n", (uint32_t) byteOffset);
		printfCUCA("<leerNBloquesNivel2> sizeBytes: %d\n", sizeBytes);
		uint64_t byteFin = byteOffset + sizeBytes;
		div_t divInicio = div(byteOffset, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize);
		uint16_t punteroBiIndInicio = divInicio.quot;
		div_t divFin = div(byteFin, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize);
		uint16_t punteroBiIndFin = divFin.quot;
		off_t offsetFinal = divFin.rem;
		if (divFin.rem == 0 && divFin.quot > 0) {
			punteroBiIndFin--;
			offsetFinal = maxCantBloquesNivelN(2) * staticSuperBlock.blockSize; //TODO revisar que esto sea realmente necesario
			//printfCUCA("Como el offset es 0 seteo el bloque final a [%d] y el offset a [%d].\n", punteroBiIndFin, (uint32_t) offsetFinal);
		}

		uint16_t punteroActual;
		contenido = malloc(sizeBytes);

		if (punteroBiIndInicio == punteroBiIndFin) {
			//EL PRIMERO TAMBIEN ES EL ULTIMO
			punteroActual = punteroBiIndInicio;
			char* contenidoBloque = leerBloqueGlobal(puntBiInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			uint32_t* puntBiInd = malloc(staticSuperBlock.blockSize);
			memcpy(puntBiInd, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			char* contenidoAux = leerNBloquesNivel1(blockGroup, puntBiInd, divInicio.rem, sizeBytes);
			free(puntBiInd);
			memcpy(contenido, contenidoAux, sizeBytes);
			free(contenidoAux);
		} else {
			//EL PRIMERO NO ES EL ULTIMO
			//LEO EL PRIMERO
			off_t offsetGrabacion = 0;
			punteroActual = punteroBiIndInicio;
			char* contenidoBloque = leerBloqueGlobal(puntBiInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			uint32_t* puntInd = malloc(staticSuperBlock.blockSize);
			memcpy(puntInd, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			char* contenidoAux = leerNBloquesNivel1(blockGroup, puntInd, divInicio.rem, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize) - divInicio.rem);
			free(puntInd);
			memcpy(contenido, contenidoAux, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize) - divInicio.rem);
			free(contenidoAux);

			offsetGrabacion = (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize) - divInicio.rem;
			punteroActual++;

			//LEO LOS DEL MEDIO
			//SI SOLO SON DOS NO VA A ENTRAR EN EL FOR
			for (; punteroActual < punteroBiIndFin; punteroActual++) {
				contenidoBloque = leerBloqueGlobal(puntBiInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
				puntInd = malloc(staticSuperBlock.blockSize);
				memcpy(puntInd, contenidoBloque, staticSuperBlock.blockSize);
				free(contenidoBloque);
				contenidoAux = leerNBloquesNivel1(blockGroup, puntInd, 0, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize));
				free(puntInd);
				memcpy(contenido + offsetGrabacion, contenidoAux, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize);
				free(contenidoAux);

				offsetGrabacion += maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
			}

			//LEO EL DEL FINAL
			//EL PUNTERO ACTUAL ES EL PUNTERO FINAL
			contenidoBloque = leerBloqueGlobal(puntBiInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			puntInd = malloc(staticSuperBlock.blockSize);
			memcpy(puntInd, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			contenidoAux = leerNBloquesNivel1(blockGroup, puntInd, 0, offsetFinal);
			free(puntInd);
			memcpy(contenido + offsetGrabacion, contenidoAux, offsetFinal);
			free(contenidoAux);
		}
	}
	return contenido;
}

char* leerNBloquesNivel3(uint8_t blockGroup, uint32_t* puntTriInd, off_t byteOffset, size_t sizeBytes) {
	char* contenido = NULL;
	if (sizeBytes > 0) {
		printfCUCA("<leerNBloquesNivel3> offset: %d\n", (uint32_t) byteOffset);
		printfCUCA("<leerNBloquesNivel3> sizeBytes: %d\n", sizeBytes);
		uint64_t byteFin = byteOffset + sizeBytes;
		//div_t divInicio = div(byteOffset, maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
		uint16_t punteroTriIndInicio = (uint16_t) (byteOffset / (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divInicio.quot*/;
		//div_t divFin = div(byteFin, maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
		uint16_t punteroTriIndFin = (uint16_t) (byteFin / (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divFin.quot*/;
		off_t offsetFinal = (uint32_t) (byteFin % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divFin.rem*/;
		if ((byteFin % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divFin.rem*/== 0 && (byteFin / (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divFin.quot*/> 0) {
			punteroTriIndFin--;
			offsetFinal = maxCantBloquesNivelN(3) * staticSuperBlock.blockSize; //TODO revisar que esto sea realmente necesario
			//printfCUCA("Como el offset es 0 seteo el bloque final a [%d] y el offset a [%d].\n", punteroBiIndFin, (uint32_t) offsetFinal);
		}
		uint16_t punteroActual;
		contenido = malloc(sizeBytes);
		if (punteroTriIndInicio == punteroTriIndFin) {
			//EL PRIMERO TAMBIEN ES EL ULTIMO
			punteroActual = punteroTriIndInicio;
			char* contenidoBloque = leerBloqueGlobal(puntTriInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			uint32_t* puntBiInd = malloc(staticSuperBlock.blockSize);
			memcpy(puntBiInd, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			char* contenidoAux = leerNBloquesNivel2(blockGroup, puntBiInd, (byteOffset % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divInicio.rem*/, sizeBytes);
			free(puntBiInd);
			memcpy(contenido, contenidoAux, sizeBytes);
			free(contenidoAux);
		} else {
			//EL PRIMERO NO ES EL ULTIMO
			//LEO EL PRIMERO
			off_t offsetGrabacion = 0;
			punteroActual = punteroTriIndInicio;
			char* contenidoBloque = leerBloqueGlobal(puntTriInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			uint32_t* puntBiInd = malloc(staticSuperBlock.blockSize);
			memcpy(puntBiInd, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			char* contenidoAux = leerNBloquesNivel2(blockGroup, puntBiInd, (byteOffset % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divInicio.rem*/, (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize) - (byteOffset / (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divInicio.rem*/);
			free(puntBiInd);
			memcpy(contenido, contenidoAux, (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize) - (byteOffset % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divInicio.rem*/);
			free(contenidoAux);

			offsetGrabacion = (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize) - (byteOffset % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize))/*divInicio.rem*/;
			punteroActual++;

			//LEO LOS DEL MEDIO
			//SI SOLO SON DOS NO VA A ENTRAR EN EL FOR
			for (; punteroActual < punteroTriIndFin; punteroActual++) {
				contenidoBloque = leerBloqueGlobal(puntBiInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
				puntBiInd = malloc(staticSuperBlock.blockSize);
				memcpy(puntBiInd, contenidoBloque, staticSuperBlock.blockSize);
				free(contenidoBloque);
				contenidoAux = leerNBloquesNivel2(blockGroup, puntBiInd, 0, (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize));
				free(puntBiInd);
				memcpy(contenido + offsetGrabacion, contenidoAux, maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
				free(contenidoAux);
				printfCUCA("<leerNBloquesNivel3> offsetGrabacion: %llu\n", (uint64_t) offsetGrabacion);
				offsetGrabacion += maxCantBloquesNivelN(3) * staticSuperBlock.blockSize;
			}

			//LEO EL DEL FINAL
			//EL PUNTERO ACTUAL ES EL PUNTERO FINAL
			contenidoBloque = leerBloqueGlobal(puntTriInd[punteroActual])/* TODO leerBloqueLocal(blockGroup, puntDir[punteroActual])*/;
			puntBiInd = malloc(staticSuperBlock.blockSize);
			memcpy(puntBiInd, contenidoBloque, staticSuperBlock.blockSize);
			free(contenidoBloque);
			contenidoAux = leerNBloquesNivel2(blockGroup, puntBiInd, 0, offsetFinal);
			free(puntBiInd);
			memcpy(contenido + offsetGrabacion, contenidoAux, offsetFinal);
			free(contenidoAux);
		}
	}
	return contenido;
}

char* leerIndireccionamiento(uint8_t blockGroup, inodeStructure_t inodo, off_t offset, size_t size) {
//printfCUCA("Comienzo a leer los indireccionamientos.\n");
	div_t divInicio = div(offset, staticSuperBlock.blockSize);
	uint64_t bloqueInicio = divInicio.quot;
//printfCUCA("El bloque de inicio es el [%d].\n", (uint32_t) bloqueInicio);
	div_t divFin = div(offset + size, staticSuperBlock.blockSize);
	uint64_t bloqueFin = divFin.quot;
//printfCUCA("El bloque final es el [%d].\n", (uint32_t) bloqueFin);
	char* contenido = malloc(size);
	if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosDirectos(bloqueFin)) {
		//SOLO HAY QUE LEER LOS PUNTEROS DIRECTOS
		printfCUCA("Solo hay que leer los punteros directos.\n");
		char* contenidoAuxDir = leerNBloquesNivel0(blockGroup, inodo.block, offset, size);
		memcpy(contenido, contenidoAuxDir, size);
		free(contenidoAuxDir);
	} else if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosIndirectosSimples(bloqueFin)) {
		//HAY QUE LEER LOS PUNTEROS DIRECTOS Y EL INDIRECTO SIMPLE
		printfCUCA("Hay que leer los punteros directos y el indirecto simple.\n");
		printfCUCA("----------------------------------------------------------------------------------------------------\n");
		printfCUCA("Leo los punteros directos.\n");
		char* contenidoAuxDir = leerNBloquesNivel0(blockGroup, inodo.block, offset, 12 * staticSuperBlock.blockSize - offset);
		printfCUCA("Lei los punteros directos:\n");
		//uint32_t i;
		//for (i = 0; i < 12 * staticSuperBlock.blockSize - offset; i++) {
		//printfCUCA("%c", contenidoAuxDir[i]);
		//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, contenidoAuxDir[i], contenidoAuxDir[i]);
		//}
		//printfCUCA("\n\n");
		printfCUCA("----------------------------------------------------------------------------------------------------\n");
		printfCUCA("Leo el puntero indirecto.\n");
		char* contenidoAuxInd = leerNBloquesNivel1(blockGroup, inodo.block + 12, 0, (offset + size) - (12 * staticSuperBlock.blockSize));
		printfCUCA("Lei el puntero indirecto.\n");
		//for (i = 0; i < (offset + size) - (12 * staticSuperBlock.blockSize); i++) {
		//printfCUCA("%c", contenidoAuxInd[i]);
		//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, (uint32_t) contenidoAuxInd[i], (uint32_t) contenidoAuxInd[i]);
		//}
		//printfCUCA("\n\n");
		memcpy(contenido, contenidoAuxDir, 12 * staticSuperBlock.blockSize - offset);
		uint64_t desplazamiento = 12 * staticSuperBlock.blockSize - offset;
		printfCUCA("El desplazamiento es: [%d].\n", (uint32_t) desplazamiento);
		memcpy(contenido + desplazamiento, contenidoAuxInd, (offset + size) - (12 * staticSuperBlock.blockSize));
		free(contenidoAuxDir);
		free(contenidoAuxInd);
	} else if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosIndirectosDobles(bloqueFin)) {
		//HAY QUE LEER LOS PUNTEROS DIRECTOS, EL INDIRECTO SIMPLE Y EL INDIRECTO DOBLE
		printfCUCA("Hay que leer los punteros directos, el indirecto simple y el indirecto doble.\n");
		printfCUCA("----------------------------------------------------------------------------------------------------\n");
		printfCUCA("Leo los punteros directos.\n");
		char* contenidoAuxDir = leerNBloquesNivel0(blockGroup, inodo.block, offset, 12 * staticSuperBlock.blockSize - offset);
		printfCUCA("Lei los punteros directos:\n");
		//uint32_t i;
		//for (i = 0; i < 12 * staticSuperBlock.blockSize - offset; i++) {
		//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, contenidoAuxDir[i], contenidoAuxDir[i]);
		//}
		printfCUCA("----------------------------------------------------------------------------------------------------\n");
		printfCUCA("Leo el puntero indirecto.\n");
		char* contenidoAuxInd = leerNBloquesNivel1(blockGroup, inodo.block + 12, 0, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize));
		printfCUCA("Lei el puntero indirecto.\n");
		//for (i = 0; i < (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize); i++) {
		//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, (uint32_t) contenidoAuxInd[i], (uint32_t) contenidoAuxInd[i]);
		//}
		printfCUCA("----------------------------------------------------------------------------------------------------\n");
		printfCUCA("Leo el puntero doblemente indirecto.\n");
		char* contenidoAuxBiInd = leerNBloquesNivel2(blockGroup, inodo.block + 13, 0, (offset + size) - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize));
		printfCUCA("Lei el puntero doblemente indirecto.\n");
		//for (i = 0; i < (offset + size) - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize); i++) {
		//printfCUCA("Byte:[%d] -- Contenido:[%d]:[%c]\n", i, (uint32_t) contenidoAuxBiInd[i], (uint32_t) contenidoAuxBiInd[i]);
		//}
		memcpy(contenido, contenidoAuxDir, 12 * staticSuperBlock.blockSize - offset);
		uint64_t desplazamiento = 12 * staticSuperBlock.blockSize - offset;
		memcpy(contenido + desplazamiento, contenidoAuxInd, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize));
		desplazamiento += maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
		memcpy(contenido + desplazamiento, contenidoAuxBiInd, (offset + size) - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize));
		free(contenidoAuxDir);
		free(contenidoAuxInd);
		free(contenidoAuxBiInd);
	} else if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		//HAY QUE LEER LOS PUNTEROS DIRECTOS, EL INDIRECTO SIMPLE, EL INDIRECTO DOBLE Y EL INDIRECTO TRIPLE
		printfCUCA("Hay que leer los punteros directos, el indirecto simple, el indirecto doble y el indirecto triple.\n");
		char* contenidoAuxDir = leerNBloquesNivel0(blockGroup, inodo.block, offset, 12 * staticSuperBlock.blockSize - offset);
		char* contenidoAuxInd = leerNBloquesNivel1(blockGroup, inodo.block + 12, 0, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize));
		char* contenidoAuxBiInd = leerNBloquesNivel2(blockGroup, inodo.block + 13, 0, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize));
		char* contenidoAuxTriInd = leerNBloquesNivel3(blockGroup, inodo.block + 14, 0, (offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize));
		memcpy(contenido, contenidoAuxDir, 12 * staticSuperBlock.blockSize - offset);
		uint64_t desplazamiento = 12 * staticSuperBlock.blockSize - offset;
		memcpy(contenido + desplazamiento, contenidoAuxInd, (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize));
		desplazamiento += maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
		memcpy(contenido + desplazamiento, contenidoAuxBiInd, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize));
		desplazamiento += maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
		memcpy(contenido + desplazamiento, contenidoAuxTriInd, (offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize));
		free(contenidoAuxDir);
		free(contenidoAuxInd);
		free(contenidoAuxBiInd);
		free(contenidoAuxTriInd);
	} else if (estaEntrePunterosIndirectosTriples(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		//SOLO HAY QUE LEER EL PUNTERO INDIRECTO TRIPLE
		printfCUCA("==================================================================================\n");
		printfCUCA("<SÓLO TRIPLES> blockGroup: %d\n", blockGroup);
		printfCUCA("<SÓLO TRIPLES> offset: %d\n", (uint32_t) (offset - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize)));
		printfCUCA("<SÓLO TRIPLES> size: %d\n", size);
		printfCUCA("==================================================================================\n");
		char* contenidoAuxTriInd = leerNBloquesNivel3(blockGroup, inodo.block + 14, offset - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), size);
		memcpy(contenido, contenidoAuxTriInd, size);
		free(contenidoAuxTriInd);
	} else if (estaEntrePunterosIndirectosDobles(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		//HAY QUE LEER EL PUNTERO INDIRECTO DOBLE Y EL INDIRECTO TRIPLE
		printfCUCA("Hay que leer  el indirecto doble y el indirecto triple.\n");
		printfCUCA("Tengo que leer desde el byte %d hasta el %d de los indirectos dobles\n", (uint32_t) (offset - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize)), (uint32_t) (((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize) - offset));
		char* contenidoAuxBiInd = leerNBloquesNivel2(blockGroup, inodo.block + 13, offset - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize) - offset);
		printfCUCA("Tengo que leer desde el byte %d hasta el %d de los indirectos triples\n", 0, (uint32_t) ((offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize)));
		char* contenidoAuxTriInd = leerNBloquesNivel3(blockGroup, inodo.block + 14, 0, (offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize));
		printfCUCA("Ya lei, devuelvo el contenido\n");
		memcpy(contenido, contenidoAuxBiInd, ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize) - offset);
		uint64_t desplazamiento = ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize) - offset;
		memcpy(contenido + desplazamiento, contenidoAuxTriInd, /*TODO ESTE CALCULO PUEDE ESTAR MAL*/(offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize));
		free(contenidoAuxBiInd);
		free(contenidoAuxTriInd);
	} else if (estaEntrePunterosIndirectosSimples(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		//HAY QUE LEER EL PUNTERO INDIRECTO SIMPLE, EL INDIRECTO DOBLE Y EL INDIRECTO TRIPLE
		printfCUCA("Hay que leer  el indirecto simple, el indirecto doble y el indirecto triple.\n");
		char* contenidoAuxInd = leerNBloquesNivel1(blockGroup, inodo.block + 12, offset - (12 * staticSuperBlock.blockSize), ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize) - offset);
		char* contenidoAuxBiInd = leerNBloquesNivel2(blockGroup, inodo.block + 13, 0, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize));
		char* contenidoAuxTriInd = leerNBloquesNivel3(blockGroup, inodo.block + 14, 0, /*TODO ESTE CALCULO PUEDE ESTAR MAL*/(offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize));
		memcpy(contenido, contenidoAuxInd, ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize) - offset);
		uint64_t desplazamiento = ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize) - offset;
		memcpy(contenido + desplazamiento, contenidoAuxBiInd, (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize));
		desplazamiento += maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
		memcpy(contenido + desplazamiento, contenidoAuxTriInd, /*TODO ESTE CALCULO PUEDE ESTAR MAL*/(offset + size) - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize));
		free(contenidoAuxInd);
		free(contenidoAuxBiInd);
	} else if (estaEntrePunterosIndirectosSimples(bloqueInicio) && estaEntrePunterosIndirectosDobles(bloqueFin)) {
		//HAY QUE LEER EL PUNTERO INDIRECTO SIMPLE Y EL INDIRECTO DOBLE
		printfCUCA("Hay que leer  el indirecto simple y el indirecto doble.\n");
		char* contenidoAuxInd = leerNBloquesNivel1(blockGroup, inodo.block + 12, offset - (12 * staticSuperBlock.blockSize), ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize) - offset);
		char* contenidoAuxBiInd = leerNBloquesNivel2(blockGroup, inodo.block + 13, 0, /*TODO ESTE CALCULO PUEDE ESTAR MAL*/(offset + size) - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize));
		memcpy(contenido, contenidoAuxInd, ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize) - offset);
		uint64_t desplazamiento = ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize) - offset;
		memcpy(contenido + desplazamiento, contenidoAuxBiInd, /*TODO ESTE CALCULO PUEDE ESTAR MAL*/(offset + size) - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize));
		free(contenidoAuxInd);
		free(contenidoAuxBiInd);
	} else if (estaEntrePunterosIndirectosSimples(bloqueInicio) && estaEntrePunterosIndirectosSimples(bloqueFin)) {
		//HAY QUE LEER EL PUNTERO INDIRECTO SIMPLE
		printfCUCA("Hay que leer  el indirecto simple.\n");
		char* contenidoAuxInd = leerNBloquesNivel1(blockGroup, inodo.block + 12, offset - (12 * staticSuperBlock.blockSize), size);
		memcpy(contenido, contenidoAuxInd, size);
		free(contenidoAuxInd);
	} else if (estaEntrePunterosIndirectosDobles(bloqueInicio) && estaEntrePunterosIndirectosDobles(bloqueFin)) {
		//HAY QUE LEER EL PUNTERO INDIRECTO DOBLE
		printfCUCA("Hay que leer  el indirecto doble.\n");
		char* contenidoAuxBiInd = leerNBloquesNivel2(blockGroup, inodo.block + 13, offset - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), size);
		memcpy(contenido, contenidoAuxBiInd, size);
		free(contenidoAuxBiInd);
	}
	return contenido;
}

void escribirNBloquesNivel0(uint8_t blockGroup, uint32_t* puntDir, off_t byteOffset, size_t sizeBytes, char* buffer) {
	//printfCUCA("-------------------------ESCRIBIR N BLOQUES NIVEL 0----------------------------\n");
	if (sizeBytes > 0) {
		uint64_t byteFin = byteOffset + sizeBytes;
		div_t divInicio = div(byteOffset, staticSuperBlock.blockSize);
		uint16_t bloqueInicio = divInicio.quot;
		div_t divFin = div(byteFin, staticSuperBlock.blockSize);
		uint16_t bloqueFin = divFin.quot;
		//printfCUCA("--> bloqueInicio : %i\n", bloqueInicio);
		//printfCUCA("--> bloqueFin : %i\n\n", bloqueFin);
		uint16_t punteroActual;
		uint32_t sizeEscribir;
		off_t offsetGrabacion = 0;
		off_t offsetFinal = divFin.rem;
		punteroActual = bloqueInicio;
		if (divFin.rem == 0 && divFin.quot > 0) {
			bloqueFin--;
			offsetFinal = staticSuperBlock.blockSize;
		}
		for (; punteroActual <= bloqueFin; punteroActual++) {
			//printfCUCA("\n    --> punteroActual : %i \n", punteroActual);
			if (bloqueInicio == bloqueFin) {
				byteOffset = divInicio.rem;
				sizeEscribir = sizeBytes;
			} else {
				if (punteroActual == bloqueInicio) {
					byteOffset = divInicio.rem;
					sizeEscribir = staticSuperBlock.blockSize - byteOffset;
					offsetGrabacion = 0;
				} else if (punteroActual == bloqueFin) {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = offsetFinal;
					//offsetGrabacion += staticSuperBlock.blockSize;
				} else {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = staticSuperBlock.blockSize;
					//offsetGrabacion += staticSuperBlock.blockSize;
				}
			}
			if (sizeEscribir != 0) {
				printfCUCA("===============================================================================\n");
				printfCUCA("                              > ESCRIBIR BLOQUE <                              \n");
				//printfCUCA("            --> puntDir[punteroActual] : %i \n", puntDir[punteroActual]);
				//printfCUCA("            --> (puntDir[punteroActual] * 1024) + byteOffset : %d \n", (uint32_t)((puntDir[punteroActual] * staticSuperBlock.blockSize) + byteOffset));
				//printfCUCA("            --> staticSuperBlock.blockSize : %i \n", (uint32_t) staticSuperBlock.blockSize);
				//printfCUCA("            --> byteOffset : %i \n", (uint32_t) byteOffset);
				//printfCUCA("            --> sizeEscribir : %i \n", sizeEscribir);
				//printfCUCA("            --> offsetGrabacion : %i \n", (uint32_t) offsetGrabacion);
				printfCUCA("> blockGroup : %i\n", blockGroup);
				printfCUCA("> puntDir[punteroActual] : %i\n", puntDir[punteroActual]);
				printfCUCA("> byteOffset : %i\n", (uint32_t) byteOffset);
				printfCUCA("> sizeEscribir : %i \n", sizeEscribir);
				printfCUCA("> offsetGrabacion : %i \n", (uint32_t) offsetGrabacion);
				printfCUCA("> buffer : ");
				if (todosLosCaracteresIguales(buffer, sizeEscribir)) {
					printfCUCA("%i caracteres iguales\n", sizeEscribir);
				} else {
					printfCUCA("%i caracteres mixtos\n", sizeEscribir);
				}
				//escribirBytes(((off_t) puntDir[punteroActual] * staticSuperBlock.blockSize) + byteOffset, (size_t) sizeEscribir, buffer + offsetGrabacion);
				escribirParteBloqueGlobal(puntDir[punteroActual], (uint64_t) byteOffset, (uint64_t) (byteOffset + sizeEscribir), buffer + offsetGrabacion);
			}
		}
	}
}

void escribirNBloquesNivel1(uint8_t blockGroup, uint32_t *puntInd, off_t byteOffset, size_t sizeBytes, char *buffer) {
	if (sizeBytes > 0) {
		uint64_t byteFin = byteOffset + sizeBytes;
		div_t divInicio = div(byteOffset, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize);
		uint16_t punteroIndInicio = divInicio.quot;
		div_t divFin = div(byteFin, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize);
		uint16_t punteroIndFin = divFin.quot;
		off_t offsetFinal = divFin.rem;
		if (divFin.rem == 0 && divFin.quot > 0) {
			punteroIndFin--;
			offsetFinal = maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
		}
		uint16_t punteroActual;
		punteroActual = punteroIndInicio;
		off_t offsetGrabacion = 0;
		uint32_t sizeEscribir;
		//printfCUCA("-------------------------ESCRIBIR N BLOQUES NIVEL 1----------------------------\n");
		//printfCUCA("--> punteroIndInicio : %i\n", punteroIndInicio);
		//printfCUCA("--> punteroIndFin : %i \n\n", punteroIndFin);
		for (; punteroActual <= punteroIndFin; punteroActual++) {
			//printfCUCA("    --> punteroIndActual : %i \n", punteroActual);
			if (punteroIndInicio == punteroIndFin) {
				byteOffset = divInicio.rem;
				sizeEscribir = sizeBytes;
			} else {
				if (punteroActual == punteroIndInicio) {
					byteOffset = divInicio.rem;
					sizeEscribir = (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) - byteOffset;
					offsetGrabacion = 0;
				} else if (punteroActual == punteroIndFin) {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = offsetFinal;
				} else {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
					//offsetGrabacion += maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
				}
			}
			uint32_t *puntDir = (uint32_t*) leerBloqueGlobal(puntInd[punteroActual]);
			//printfCUCA("\n--> Le voy a pasar a escribirNBloquesNivel0: \n");
			//printfCUCA("    --> puntDir : %d \n", (uint32_t) puntDir);
			//printfCUCA("    --> byteOffset : %i\n", (uint32_t) byteOffset);
			//printfCUCA("    --> sizeEscribir : %i\n", sizeEscribir);
			//3printfCUCA("    --> offsetGrabacion : %i\n", (uint32_t) offsetGrabacion);

			escribirNBloquesNivel0(blockGroup, puntDir, byteOffset, sizeEscribir, buffer + offsetGrabacion);
			free(puntDir);
		}

	}
}

void escribirNBloquesNivel2(uint8_t blockGroup, uint32_t* puntBiInd, off_t byteOffset, size_t sizeBytes, char *buffer) {
	if (sizeBytes > 0) {
		//printfCUCA("-------------------------ESCRIBIR N BLOQUES NIVEL 2----------------------------\n");
		uint64_t byteFin = byteOffset + sizeBytes;
		div_t divInicio = div(byteOffset, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize);
		uint16_t punteroBiIndInicio = divInicio.quot;
		div_t divFin = div(byteFin, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize);
		uint16_t punteroBiIndFin = divFin.quot;
		off_t offsetFinal = divFin.rem;
		if (divFin.rem == 0 && divFin.quot > 0) {
			punteroBiIndFin--;
			offsetFinal = maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
		}
		//printfCUCA("--> punteroBiIndInicio : %i\n", punteroBiIndInicio);
		//printfCUCA("--> punteroBiIndFin : %i\n", punteroBiIndFin);
		uint16_t punteroActual;
		punteroActual = punteroBiIndInicio;
		off_t offsetGrabacion = 0;
		uint32_t sizeEscribir;
		for (; punteroActual <= punteroBiIndFin; punteroActual++) {
			if (punteroBiIndInicio == punteroBiIndFin) {
				byteOffset = divInicio.rem;
				sizeEscribir = sizeBytes;
			} else {
				if (punteroActual == punteroBiIndInicio) {
					byteOffset = divInicio.rem;
					sizeEscribir = (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize) - byteOffset;
					offsetGrabacion = 0;
				} else if (punteroActual == punteroBiIndFin) {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = offsetFinal;
					//offsetGrabacion += maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
				} else {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
					//offsetGrabacion += maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
				}
			}
			/*
			 char *contenidoBloque = leerBloqueGlobal(puntBiInd[punteroActual]);
			 uint32_t *puntInd = malloc(staticSuperBlock.blockSize);
			 memcpy(puntInd, contenidoBloque, staticSuperBlock.blockSize);
			 free(contenidoBloque);
			 */

			uint32_t *puntInd = (uint32_t*) leerBloqueGlobal(puntBiInd[punteroActual]);
			//printfCUCA("\n--> Le voy a pasar a escribirNBloquesNivel1: \n");
			//printfCUCA("    --> puntInd : [%d]\n", (uint32_t) puntInd);
			//printfCUCA("    --> byteOffset : [%d]\n", (uint32_t) byteOffset);
			//printfCUCA("    --> sizeEscribir : [%d]\n", sizeEscribir);

			escribirNBloquesNivel1(blockGroup, puntInd, byteOffset, sizeEscribir, buffer + offsetGrabacion);
			free(puntInd);
		}
	}
}

void escribirNBloquesNivel3(uint8_t blockGroup, uint32_t *puntTriInd, off_t byteOffset, size_t sizeBytes, char*buffer) {
	struct {
		uint32_t quot;
		uint32_t rem;
	} divInicio;
	struct {
		uint32_t quot;
		uint32_t rem;
	} divFin;
	if (sizeBytes > 0) {
		uint64_t byteFin = byteOffset + sizeBytes;
		divInicio.quot = byteOffset / (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
		divInicio.rem = byteOffset % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
		uint16_t punteroTriIndInicio = divInicio.quot;
		divFin.quot = byteFin / (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
		divFin.rem = byteFin % (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize);
		uint16_t punteroTriIndFin = divFin.quot;
		off_t offsetFinal = divFin.rem;
		if (divFin.rem == 0 && divFin.quot > 0) {
			punteroTriIndFin--;
			offsetFinal = maxCantBloquesNivelN(3) * staticSuperBlock.blockSize;
		}
		uint16_t punteroActual;
		punteroActual = punteroTriIndInicio;
		off_t offsetGrabacion = 0;
		uint32_t sizeEscribir;
		for (; punteroActual <= punteroTriIndFin; punteroActual++) {
			if (punteroTriIndInicio == punteroTriIndFin) {
				byteOffset = divInicio.rem;
				sizeEscribir = sizeBytes;
			} else {
				if (punteroActual == punteroTriIndInicio) {
					byteOffset = divInicio.rem;
					sizeEscribir = (maxCantBloquesNivelN(3) * staticSuperBlock.blockSize) - byteOffset;
					offsetGrabacion = 0;
				} else if (punteroActual == punteroTriIndFin) {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = offsetFinal;
				} else {
					byteOffset = 0;
					offsetGrabacion += sizeEscribir;
					sizeEscribir = maxCantBloquesNivelN(3) * staticSuperBlock.blockSize;
				}
			}
			uint32_t *puntBiInd = (uint32_t*) leerBloqueGlobal(puntTriInd[punteroActual]);
			escribirNBloquesNivel2(blockGroup, puntBiInd, byteOffset, sizeEscribir, buffer + offsetGrabacion);
			free(puntBiInd);
		}
	}
}

uint8_t todosLosCaracteresIguales(char *string, uint32_t size) {
	char *primerCaracter = (char*) malloc(1);
	primerCaracter[0] = string[0];
	uint32_t i;
	uint8_t todosIguales = 1;
	for (i = 0; i < size && todosIguales; i++) {
		if (string[i] != primerCaracter[0]) {
			todosIguales = 0;
		}
	}
	free(primerCaracter);
	return todosIguales;
}

void escribirIndireccionamiento(uint8_t numBlockGroup, inodeStructure_t inodo, size_t size, off_t offset, char *buf) {
	//imprimirContenidoInodo(inodo);
	div_t divInicio = div(offset, staticSuperBlock.blockSize);
	div_t divFin = div(offset + size, staticSuperBlock.blockSize);
	uint64_t bloqueInicio = divInicio.quot;
	uint64_t bloqueFin = divFin.quot;
	//printfCUCA("-------------------------------------------------------------------------------\n");
	//printfCUCA("size : %i \n", (uint32_t) size);
	//printfCUCA("buffer : ");
	//if (todosLosCaracteresIguales(buf, (uint32_t) size)) {
	//	printfCUCA("%i caracteres iguales \n", (uint32_t) size);
	//} else {
	//	printfCUCA("%i caracteres mixtos \n", (uint32_t) size);
	//}
	if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosDirectos(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                   > ESCRIBIR SÓLAMENTE BLOQUES DIRECTOS <                     \n");
		escribirNBloquesNivel0(numBlockGroup, inodo.block, offset, size, (char*) buf);
	} else if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosIndirectosSimples(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                  > BLOQUES DIRECTOS + INDIRECCIÓN SIMPLE <                    \n");
		size_t bytesDirectos = 12 * staticSuperBlock.blockSize - offset;
		size_t bytesIndirectosSimples = size - bytesDirectos;
		char *bufferDirecto = (char*) malloc(bytesDirectos);
		//uint32_t i;
		//for (i = 0; i < bytesDirectos; i++) {
		//printfCUCA("%c", bufferDirecto[i]);
		//}
		//printfCUCA("\n\n");
		char *bufferIndirectoSimple = (char*) malloc(bytesIndirectosSimples);
		//for (i = 0; i < bytesIndirectosSimples; i++) {
		//printfCUCA("%c", bufferDirecto[i]);
		//}
		//printfCUCA("\n\n");
		memcpy(bufferDirecto, buf, bytesDirectos);
		memcpy(bufferIndirectoSimple, buf + bytesDirectos, bytesIndirectosSimples);
		/*
		 printfCUCA("\n--> bufferDirecto :");
		 uint32_t i;
		 for (i = 0; i < bytesDirectos; i++) {
		 printfCUCA("%c", bufferDirecto[i]);
		 }
		 printfCUCA("\n");

		 if (todosLosCaracteresIguales(bufferDirecto, bytesDirectos)) {
		 printfCUCA("\n%i CARACTERES IGUALES \n", bytesDirectos);
		 } else {
		 printfCUCA("\n%i CARACTERES MIXTOS \n", bytesDirectos);
		 }

		 printfCUCA("\n--> bufferIndirectoSimple :");
		 for (i = 0; i < bytesIndirectosSimples; i++) {
		 printfCUCA("%c", bufferIndirectoSimple[i]);
		 }
		 printfCUCA("\n");

		 if (todosLosCaracteresIguales(bufferIndirectoSimple, bytesIndirectosSimples)) {
		 printfCUCA("\n%i CARACTERES IGUALES \n", bytesIndirectosSimples);
		 } else {
		 printfCUCA("\n%i CARACTERES MIXTOS \n", bytesIndirectosSimples);
		 }
		 */
		escribirNBloquesNivel0(numBlockGroup, inodo.block, offset, bytesDirectos, bufferDirecto);
		escribirNBloquesNivel1(numBlockGroup, inodo.block + 12, 0, bytesIndirectosSimples, bufferIndirectoSimple);
		free(bufferDirecto);
		free(bufferIndirectoSimple);
	} else if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosIndirectosDobles(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("        > BLOQUES DIRECTOS + INDIRECCIÓN SIMPLE + INDIRECCIÓN DOBLE <          \n");
		size_t bytesDirectos = 12 * staticSuperBlock.blockSize - offset;
		size_t bytesIndirectosSimples = maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
		size_t bytesIndirectosDobles = size - bytesIndirectosSimples - bytesDirectos;
		char *bufferDirecto = (char*) malloc(bytesDirectos);
		char *bufferIndirectoSimple = (char*) malloc(bytesIndirectosSimples);
		char *bufferIndirectoDoble = (char*) malloc(bytesIndirectosDobles);
		memcpy(bufferDirecto, buf, bytesDirectos);
		memcpy(bufferIndirectoSimple, buf + bytesDirectos, bytesIndirectosSimples);
		memcpy(bufferIndirectoDoble, buf + bytesDirectos + bytesIndirectosSimples, bytesIndirectosDobles);
		escribirNBloquesNivel0(numBlockGroup, inodo.block, offset, bytesDirectos, bufferDirecto);
		escribirNBloquesNivel1(numBlockGroup, inodo.block + 12, 0, bytesIndirectosSimples, bufferIndirectoSimple);
		escribirNBloquesNivel2(numBlockGroup, inodo.block + 13, 0, bytesIndirectosDobles, bufferIndirectoDoble);
		free(bufferDirecto);
		free(bufferIndirectoSimple);
		free(bufferIndirectoDoble);
	} else if (estaEntrePunterosDirectos(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("   > DIRECTOS + INDIRECCIÓN SIMPLE + INDIRECCIÓN DOBLE + INDIRECCIÓN TRIPLE <  \n");
		size_t bytesDirectos = 12 * staticSuperBlock.blockSize - offset;
		size_t bytesIndirectosSimples = maxCantBloquesNivelN(1) * staticSuperBlock.blockSize;
		size_t bytesIndirectosDobles = maxCantBloquesNivelN(2) * staticSuperBlock.blockSize;
		size_t bytesIndirectosTriples = size - bytesIndirectosDobles - bytesIndirectosSimples - bytesDirectos;
		char *bufferDirecto = (char*) malloc(bytesDirectos);
		char *bufferIndirectoSimple = (char*) malloc(bytesIndirectosSimples);
		char *bufferIndirectoDoble = (char*) malloc(bytesIndirectosDobles);
		char *bufferIndirectoTriple = (char*) malloc(bytesIndirectosTriples);
		memcpy(bufferDirecto, buf, bytesDirectos);
		memcpy(bufferIndirectoSimple, buf + bytesDirectos, bytesIndirectosSimples);
		memcpy(bufferIndirectoDoble, buf + bytesDirectos + bytesIndirectosSimples, bytesIndirectosDobles);
		memcpy(bufferIndirectoTriple, buf + bytesDirectos + bytesIndirectosSimples + bytesIndirectosDobles, bytesIndirectosTriples);
		escribirNBloquesNivel0(numBlockGroup, inodo.block, offset, bytesDirectos, bufferDirecto);
		escribirNBloquesNivel1(numBlockGroup, inodo.block + 12, 0, bytesIndirectosSimples, bufferIndirectoSimple);
		escribirNBloquesNivel2(numBlockGroup, inodo.block + 13, 0, bytesIndirectosDobles, bufferIndirectoDoble);
		escribirNBloquesNivel3(numBlockGroup, inodo.block + 14, 0, bytesIndirectosTriples, bufferIndirectoTriple);
		free(bufferDirecto);
		free(bufferIndirectoSimple);
		free(bufferIndirectoDoble);
		free(bufferIndirectoTriple);
	} else if (estaEntrePunterosIndirectosTriples(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                  > ESCRIBIR SÓLAMENTE INDIRECCIÓN TRIPLE <                    \n");
		escribirNBloquesNivel3(numBlockGroup, inodo.block + 14, offset - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), size, buf);
	} else if (estaEntrePunterosIndirectosDobles(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                 > INDIRECCIÓN DOBLE + INDIRECCIÓN TRIPLE <                    \n");
		size_t bytesIndirectosDobles = (12 * staticSuperBlock.blockSize) + (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) + (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize) - offset;
		size_t bytesIndirectosTriples = size - bytesIndirectosDobles;
		char *bufferIndirectoDoble = (char*) malloc(bytesIndirectosDobles);
		char *bufferIndirectoTriple = (char*) malloc(bytesIndirectosTriples);
		memcpy(bufferIndirectoDoble, buf, bytesIndirectosDobles);
		memcpy(bufferIndirectoTriple, buf + bytesIndirectosDobles, bytesIndirectosTriples);
		escribirNBloquesNivel2(numBlockGroup, inodo.block + 13, offset - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), bytesIndirectosDobles, bufferIndirectoDoble);
		escribirNBloquesNivel3(numBlockGroup, inodo.block + 14, 0, bytesIndirectosTriples, bufferIndirectoTriple);
		free(bufferIndirectoDoble);
		free(bufferIndirectoTriple);
	} else if (estaEntrePunterosIndirectosSimples(bloqueInicio) && estaEntrePunterosIndirectosTriples(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("       > INDIRECCIÓN SIMPLE + INDIRECCIÓN DOBLE + INDIRECCIÓN TRIPLE <         \n");
		size_t bytesIndirectosSimples = (12 * staticSuperBlock.blockSize) + (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) - offset;
		size_t bytesIndirectosDobles = (maxCantBloquesNivelN(2) * staticSuperBlock.blockSize);
		size_t bytesIndirectosTriples = size - bytesIndirectosDobles - bytesIndirectosSimples;
		char *bufferIndirectoSimple = (char*) malloc(bytesIndirectosSimples);
		char *bufferIndirectoDoble = (char*) malloc(bytesIndirectosDobles);
		char *bufferIndirectoTriple = (char*) malloc(bytesIndirectosTriples);
		memcpy(bufferIndirectoSimple, buf, bytesIndirectosSimples);
		memcpy(bufferIndirectoDoble, buf + bytesIndirectosSimples, bytesIndirectosDobles);
		memcpy(bufferIndirectoTriple, buf + bytesIndirectosSimples + bytesIndirectosDobles, bytesIndirectosTriples);
		escribirNBloquesNivel1(numBlockGroup, inodo.block + 12, offset - (12 * staticSuperBlock.blockSize), bytesIndirectosSimples, bufferIndirectoSimple);
		escribirNBloquesNivel2(numBlockGroup, inodo.block + 13, 0, bytesIndirectosDobles, bufferIndirectoDoble);
		escribirNBloquesNivel3(numBlockGroup, inodo.block + 14, 0, bytesIndirectosTriples, bufferIndirectoTriple);
		free(bufferIndirectoSimple);
		free(bufferIndirectoDoble);
		free(bufferIndirectoTriple);
	} else if (estaEntrePunterosIndirectosSimples(bloqueInicio) && estaEntrePunterosIndirectosDobles(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                  > INDIRECCIÓN SIMPLE + INDIRECCIÓN DOBLE <                   \n");
		size_t bytesIndirectosSimples = (12 * staticSuperBlock.blockSize) + (maxCantBloquesNivelN(1) * staticSuperBlock.blockSize) - offset;
		size_t bytesIndirectosDobles = size - bytesIndirectosSimples;
		char *bufferIndirectoSimple = (char*) malloc(bytesIndirectosSimples);
		char *bufferIndirectoDoble = (char*) malloc(bytesIndirectosDobles);
		memcpy(bufferIndirectoSimple, buf, bytesIndirectosSimples);
		memcpy(bufferIndirectoDoble, buf + bytesIndirectosSimples, bytesIndirectosDobles);
		/*
		 printfCUCA("\n--> bufferIndirectoSimple :");
		 uint32_t i;
		 for (i = 0; i < bytesIndirectosSimples; i++) {
		 printfCUCA("%c", bufferIndirectoSimple[i]);
		 }
		 printfCUCA("\n");

		 if (todosLosCaracteresIguales(bufferIndirectoSimple, bytesIndirectosSimples)) {
		 printfCUCA("\n%i CARACTERES IGUALES \n", bytesIndirectosSimples);
		 } else {
		 printfCUCA("\n%i CARACTERES MIXTOS \n", bytesIndirectosSimples);
		 }

		 printfCUCA("\n--> bufferIndirectoDoble :");
		 for (i = 0; i < bytesIndirectosDobles; i++) {
		 printfCUCA("%c", bufferIndirectoDoble[i]);
		 }
		 printfCUCA("\n");

		 if (todosLosCaracteresIguales(bufferIndirectoDoble, bytesIndirectosDobles)) {
		 printfCUCA("\n%i CARACTERES IGUALES \n", bytesIndirectosDobles);
		 } else {
		 printfCUCA("\n%i CARACTERES MIXTOS \n", bytesIndirectosDobles);
		 }
		 */
		escribirNBloquesNivel1(numBlockGroup, inodo.block + 12, offset - (12 * staticSuperBlock.blockSize), bytesIndirectosSimples, bufferIndirectoSimple);
		escribirNBloquesNivel2(numBlockGroup, inodo.block + 13, 0, bytesIndirectosDobles, bufferIndirectoDoble);
		free(bufferIndirectoSimple);
		free(bufferIndirectoDoble);
	} else if (estaEntrePunterosIndirectosSimples(bloqueInicio) && estaEntrePunterosIndirectosSimples(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                  > ESCRIBIR SÓLAMENTE INDIRECCIÓN SIMPLE <                    \n");
		escribirNBloquesNivel1(numBlockGroup, inodo.block + 12, offset - (12 * staticSuperBlock.blockSize), size, buf);
	} else if (estaEntrePunterosIndirectosDobles(bloqueInicio) && estaEntrePunterosIndirectosDobles(bloqueFin)) {
		printfCUCA("===============================================================================\n");
		printfCUCA("                   > ESCRIBIR SÓLAMENTE INDIRECCIÓN DOBLE <                    \n");
		//printfCUCA("--> Le voy a pasar a 'escribirNBloquesNivel2:\n");
		//printfCUCA("    --> inodo.block + 13 : [%d]\n", (uint32_t)(inodo.block + 13));
		//printfCUCA("    --> cuenta loca del offset : [%d]\n", (uint32_t)(offset - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize)));
		//printfCUCA("    --> size : [%d]\n", (uint32_t) size);
		escribirNBloquesNivel2(numBlockGroup, inodo.block + 13, offset - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), size, buf);
	}
}

//----------------------------------------------------------------------------------------------------
//OBTENER UN INODO A PARTIR DE UN PATH
//----------------------------------------------------------------------------------------------------

/*uint8_t buscarEnDirBloque(uint8_t* blockGroup, char* bloque, uint64_t cantBytes, char* nombre, inodeStructure_t* inodoBuscado) {
 uint8_t encontrado = 0;
 uint64_t i;
 for (i = 0; i < cantBytes && !encontrado;) {
 uint64_t iAux = i;
 if ((iAux + 4) < cantBytes) {
 uint32_t numInodo;
 memcpy(&numInodo, bloque + i, 4);
 iAux += 4;
 if ((iAux + 2) < cantBytes) {
 uint16_t longRegistro;
 if(longRegistro > 0){
 memcpy(&longRegistro, bloque + iAux, 2);
 iAux += 2;
 if ((iAux + 1) < cantBytes) {
 uint8_t longNombre;
 memcpy(&longNombre, bloque + iAux, 1);
 iAux += 1;
 if ((iAux + longNombre) < cantBytes) {
 char* nombreAux = malloc(longNombre + 1);
 memset(nombreAux, '\0', longNombre + 1);
 memcpy(nombreAux, bloque + iAux, longNombre);
 iAux += longNombre;
 if (strcmp(nombreAux, nombre) == 0) {
 encontrado = 1;
 //TODO revisasr
 *blockGroup = numInodo / staticSuperBlock.inodesPerGroup;
 //TODO SE PUEDE OPTIMIZAR EVITANDO LEER LA INODE TABLE COMPLETA
 inodeStructure_t* inodeTable = leerInodeTable(*blockGroup);
 memcpy(inodoBuscado, &(inodeTable[numInodo % staticSuperBlock.inodesPerGroup]), sizeof(inodeStructure_t));
 }
 div_t division = div(longRegistro, 4);
 i += division.quot * 4;
 if (division.rem != 0) {
 i++;
 }
 }
 }
 }else{
 i+=4;
 }
 }
 }
 }
 return encontrado;
 }*/

/*uint8_t buscarEnDirNivel0(uint8_t *blockGroup, uint32_t* bloques, uint64_t maxCantBloques, char* nombre, inodeStructure_t* inodoBuscado) {
 uint8_t encontrado = 0;
 uint32_t i;
 for (i = 0; !encontrado && i < maxCantBloques && !encontrado; i++) {
 char* buffer = leerBloqueLocal(*blockGroup, bloques[i]);
 uint32_t tamanioBloque = staticSuperBlock.blockSize;
 char* bloquesAux = (char*) malloc(tamanioBloque);
 memset(bloquesAux, 0, tamanioBloque);
 memcpy(bloquesAux, buffer, tamanioBloque);
 encontrado = buscarEnDirBloque(blockGroup, bloquesAux, tamanioBloque, nombre, inodoBuscado);
 free(bloquesAux);
 }
 return encontrado;
 }*/

/*uint8_t buscarEnDirNivel1(uint8_t *blockGroup, uint32_t* bloques, uint64_t maxCantBloques, char* nombre, inodeStructure_t* inodoBuscado) {
 //TODO REVISAR ESTA DIVISION
 div_t division = div(maxCantBloques, maxCantBloquesIndirectosSimples());
 uint64_t cantPunteros = division.quot;
 if (division.rem != 0) {
 cantPunteros++;
 }
 uint8_t encontrado = 0;
 uint32_t i;
 for (i = 0; !encontrado && i < cantPunteros && !encontrado; i++) {
 char* buffer = leerBloqueLocal(*blockGroup, bloques[i]);
 uint32_t tamanioBloque = staticSuperBlock.blockSize;
 uint32_t* bloquesAux = (uint32_t*) malloc(tamanioBloque);
 memset(bloquesAux, 0, tamanioBloque);
 memcpy(bloquesAux, buffer, tamanioBloque);
 encontrado = buscarEnDirNivel0(blockGroup, bloquesAux, tamanioBloque / sizeof(uint32_t), nombre, inodoBuscado);
 free(bloquesAux);
 }
 return encontrado;
 }*/

/*uint8_t buscarEnDirNivel2(uint8_t *blockGroup, uint32_t* bloques, uint64_t maxCantBloques, char* nombre, inodeStructure_t* inodoBuscado) {
 //TODO REVISAR ESTA DIVISION
 div_t division = div(maxCantBloques, maxCantBloquesIndirectosDobles());
 uint64_t cantPunteros = division.quot;
 if (division.rem != 0) {
 cantPunteros++;
 }
 uint8_t encontrado = 0;
 uint32_t i;
 for (i = 0; !encontrado && i < cantPunteros && !encontrado; i++) {
 char* buffer = leerBloqueLocal(*blockGroup, bloques[i]);
 uint32_t tamanioBloque = staticSuperBlock.blockSize;
 uint32_t* bloquesAux = (uint32_t*) malloc(tamanioBloque);
 memset(bloquesAux, 0, tamanioBloque);
 memcpy(bloquesAux, buffer, tamanioBloque);
 encontrado = buscarEnDirNivel1(blockGroup, bloquesAux, tamanioBloque / sizeof(uint32_t), nombre, inodoBuscado);
 free(bloquesAux);
 }
 return encontrado;
 }*/

/*uint8_t buscarEnDirNivel3(uint8_t *blockGroup, uint32_t* bloques, uint64_t maxCantBloques, char* nombre, inodeStructure_t* inodoBuscado) {
 //TODO REVISAR ESTA DIVISION
 div_t division = div(maxCantBloques, maxCantBloquesIndirectosTriples());
 uint64_t cantPunteros = division.quot;
 if (division.rem != 0) {
 cantPunteros++;
 }
 uint8_t encontrado = 0;
 uint32_t i;
 for (i = 0; !encontrado && i < cantPunteros && !encontrado; i++) {
 char* buffer = leerBloqueLocal(*blockGroup, bloques[i]);
 uint32_t tamanioBloque = staticSuperBlock.blockSize;
 uint32_t* bloquesAux = (uint32_t*) malloc(tamanioBloque);
 memset(bloquesAux, 0, tamanioBloque);
 memcpy(bloquesAux, buffer, tamanioBloque);
 encontrado = buscarEnDirNivel2(blockGroup, bloquesAux, tamanioBloque / sizeof(uint32_t), nombre, inodoBuscado);
 free(bloquesAux);
 }
 return encontrado;
 }*/

uint8_t buscarEnDir(uint8_t *numBlockGroup, inodeStructure_t inodoDir, char* nombre, inodeStructure_t* inodoBuscado, uint32_t* numInodo) {
//TODO revisar
	/*uint8_t encontrado = 0;
	 uint32_t* bloques = (uint32_t*) malloc(12 * sizeof(uint32_t));
	 memcpy(bloques, inodoDir.block, 12 * sizeof(uint32_t));
	 uint64_t cantPunteros;
	 if (inodoDir.blocks < 12) {
	 cantPunteros = inodoDir.blocks;
	 } else {
	 cantPunteros = 12;
	 }
	 encontrado = buscarEnDirNivel0(blockGroup, bloques, cantPunteros, nombre, inodoBuscado);
	 free(bloques);
	 if (!encontrado && inodoDir.blocks > 12) {
	 if (inodoDir.blocks < (12 + maxCantBloquesIndirectosSimples())) {
	 cantPunteros = inodoDir.blocks - 12;
	 } else {
	 cantPunteros = maxCantBloquesIndirectosSimples();
	 }
	 bloques = (uint32_t*) malloc(sizeof(uint32_t));
	 memcpy(bloques, inodoDir.block + 12, sizeof(uint32_t));
	 encontrado = buscarEnDirNivel1(blockGroup, bloques, cantPunteros, nombre, inodoBuscado);
	 free(bloques);
	 if (!encontrado && inodoDir.blocks > (12 + maxCantBloquesIndirectosSimples())) {
	 if (inodoDir.blocks < (12 + maxCantBloquesIndirectosSimples() + maxCantBloquesIndirectosDobles())) {
	 cantPunteros = inodoDir.blocks - 12 - maxCantBloquesIndirectosSimples();
	 } else {
	 cantPunteros = maxCantBloquesIndirectosDobles();
	 }
	 bloques = (uint32_t*) malloc(sizeof(uint32_t));
	 memcpy(bloques, inodoDir.block + 13, sizeof(uint32_t));
	 encontrado = buscarEnDirNivel2(blockGroup, bloques, cantPunteros, nombre, inodoBuscado);
	 free(bloques);
	 if (!encontrado && inodoDir.blocks > (12 + maxCantBloquesIndirectosSimples() + maxCantBloquesIndirectosDobles())) {
	 if (inodoDir.blocks < (12 + maxCantBloquesIndirectosSimples() + maxCantBloquesIndirectosDobles() + maxCantBloquesIndirectosTriples())) {
	 cantPunteros = inodoDir.blocks - 12 - maxCantBloquesIndirectosSimples() - maxCantBloquesIndirectosDobles();
	 } else {
	 cantPunteros = maxCantBloquesIndirectosTriples();
	 }
	 bloques = (uint32_t*) malloc(sizeof(uint32_t));
	 memcpy(bloques, inodoDir.block + 14, sizeof(uint32_t));
	 encontrado = buscarEnDirNivel3(blockGroup, bloques, cantPunteros, nombre, inodoBuscado);
	 free(bloques);
	 }
	 }
	 }
	 return encontrado;*/
	printfCUCA("-------------------------------------------------------------------------------\n");
	printfCUCA("                           > BUSCAR EN DIRECTORIO <                            \n");
	char* contenidoDirectorio = leerIndireccionamiento(*numBlockGroup, inodoDir, 0, inodoDir.size);
	uint64_t i;
	uint8_t encontrado = 0;
	for (i = 0; i < inodoDir.size && !encontrado;) {
		uint64_t iAux = i;
		if ((iAux + 4) <= inodoDir.size) {
			uint32_t numInodoAux;
			memcpy(&numInodoAux, contenidoDirectorio + i, 4);
			printfCUCA("<buscarEnDir> numInodoAux: %d\n", numInodoAux);
			if (numInodoAux > 0) {
				//printfCUCA("asdfaljksdf.\n");
				*numInodo = numInodoAux - 1; //para que el primer inodo sea el 0 y no el 1
				iAux += 4;
				if ((iAux + 2) <= inodoDir.size) {
					uint16_t longRegistro;
					memcpy(&longRegistro, contenidoDirectorio + iAux, 2);
					if (longRegistro > 0) {
						printfCUCA("  --> Longitud del Registro: [%d]\n", longRegistro);
						iAux += 2;
						if ((iAux + 1) <= inodoDir.size) {
							uint8_t longNombre;
							memcpy(&longNombre, contenidoDirectorio + iAux, 1);
							printfCUCA("      --> Longitud del Nombre: [%d]\n", longNombre);
							iAux += 1;
							if ((iAux + 1) <= inodoDir.size) {
								uint8_t modo;
								memcpy(&modo, contenidoDirectorio + iAux, 1);
								printfCUCA("          --> Modo: [%d]\n", modo);
								iAux += 1;
								if ((iAux + longNombre) <= inodoDir.size) {
									char* nombreAux = malloc(longNombre + 1);
									memset(nombreAux, '\0', longNombre + 1);
									memcpy(nombreAux, contenidoDirectorio + iAux, longNombre);
									printfCUCA("<buscarEnDir> nombreAux: %s\n", nombreAux);
									if (strcmp(nombreAux, nombre) == 0) {
										printfCUCA("              --> Encontrado\n");
										encontrado = 1;
										*numBlockGroup = *numInodo / staticSuperBlock.inodesPerGroup;
										printfCUCA("<buscarEnDir> numBlockGroup %d\n", *numBlockGroup);
										//TODO SE PUEDE OPTIMIZAR EVITANDO LEER LA INODE TABLE COMPLETA
										//inodeStructure_t* inodeTable = leerInodeTable(*numBlockGroup);
										//memcpy(inodoBuscado, &(inodeTable[(*numInodo % staticSuperBlock.inodesPerGroup)]), sizeof(inodeStructure_t));
										//free(inodeTable);
										*inodoBuscado = leerInodo(*numInodo);
									}
									free(nombreAux);
									iAux += longNombre;
									div_t division = div(longRegistro, 4);
									i += division.quot * 4;
									if (division.rem != 0) {
										i += 4;
									}
								}
							}
						}
					} else {
						i += 4;
					}
				}
			} else {
				//esta entrada de directorio esta vacia
				i += 4;
			}
		}
	}
	free(contenidoDirectorio);
	return encontrado;
}

inodeStructure_t inodoDirectorioRaiz() {
//TODO revisar
	inodeStructure_t inodo = leerInodo(1);
//inodeStructure_t* inodeTablePrimerBlockGroup = leerInodeTable(0);
//memcpy(&inodo, &(inodeTablePrimerBlockGroup[1]), sizeof(inodeStructure_t));
//free(inodeTablePrimerBlockGroup);
	return inodo;
}

uint8_t obtenerInodoPath(char* path, inodeStructure_t* inodoBuscado, uint8_t* numBlockGroup, uint32_t* numInodo) {
//TODO REVISAR
	nodoNombreDirOArch_t* colaPathFte = NULL;
	nodoNombreDirOArch_t* colaPathFin = NULL;
	parsearPath(path, &colaPathFte, &colaPathFin);

	inodeStructure_t inodoAux = inodoDirectorioRaiz(); //TODO CAMBIAR ESTO DE LUGAR POR LOS SEMAFOROS
	*numInodo = 1;
	uint8_t blockGroupActual = 0;
	uint8_t encontrado;
	if (colaPathFte == NULL) {
		//ES EL DIRECTORIO RAIZ
		printfCUCA("> Es el directorio raiz\n");
		imprimirContenidoInodoExtendido(inodoAux);
		encontrado = 1;
		//bloqueo el inodo encontrado para escritura
		/*TODO*/empiezoATrabajarEnInodo(*numInodo, 1);
	} else {
		encontrado = 1;
		/*TODO*/empiezoATrabajarEnInodo(*numInodo, 0);
		while (encontrado && colaPathFte != NULL) {
			//bloqueo el directorio que voy a leer para lectura
			/**/uint32_t numInodoDir = *numInodo;
			char* nombre = NULL;
			desencolarNombreDirOArch(&colaPathFte, &colaPathFin, &nombre);
			printfCUCA("  --> Ahora busco el nombre: [%s]\n", nombre);
			encontrado = buscarEnDir(&blockGroupActual, inodoAux, nombre, &inodoAux, numInodo);
			if (encontrado) {
				//bloqueo el inodo encontrado
				if (colaPathFte == NULL) {
					//es el ultimo, lo bloqueo para escritura
					/*TODO*/empiezoATrabajarEnInodo(*numInodo, 1);
				} else {
					//no es el ultimo, lo bloqueo para lectura
					/*TODO*/empiezoATrabajarEnInodo(*numInodo, 0);
				}
				printfCUCA("  --> Encontre el inodo\n");
				imprimirContenidoInodoExtendido(inodoAux);
			}
			//desbloqueo el inodo del directorio
			/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
			free(nombre);
		}
	}
	if (colaPathFte != NULL) {
		while (colaPathFte != NULL) {
			char *nombre = NULL;
			desencolarNombreDirOArch(&colaPathFte, &colaPathFin, &nombre);
			free(nombre);
		}
	}
	if (encontrado) {
		*inodoBuscado = inodoAux;
		*numBlockGroup = blockGroupActual;
		return 0;
	} else {
		return -ENOENT;
	}
}

//----------------------------------------------------------------------------------------------------
//LECTURA DE UN DIRECTORIO
//----------------------------------------------------------------------------------------------------

nodoNombreDirOArch_t* parsearDirectorio(char* contenidoDirectorio, size_t size) {
	nodoNombreDirOArch_t* colaNombresFte = NULL;
	nodoNombreDirOArch_t* colaNombresFin = NULL;
	uint64_t i;
	uint32_t cantElementos = 0;
	for (i = 0; i < size;) {
		uint64_t iAux = i;
		if ((iAux + 4) <= size) {
			uint32_t numInodo;
			memcpy(&numInodo, contenidoDirectorio + i, 4);
			if (numInodo > 0) {
				printfCUCA("> Elemento: [%d]\n", cantElementos);
				cantElementos++;
				printfCUCA("> Numero de i-nodo: [%d]\n", numInodo); //numero de inodo arrancando en 0
				iAux += 4;
				if ((iAux + 2) <= size) {
					uint16_t longRegistro;
					memcpy(&longRegistro, contenidoDirectorio + iAux, 2);
					if (longRegistro > 0) {
						printfCUCA("  --> Longitud del registro: [%d]\n", longRegistro);
						iAux += 2;
						if ((iAux + 1) <= size) {
							uint8_t longNombre;
							memcpy(&longNombre, contenidoDirectorio + iAux, 1);
							printfCUCA("      --> Longitud del nombre: [%d]\n", longNombre);
							iAux += 1;
							if ((iAux + 1) <= size) {
								uint8_t modo;
								memcpy(&modo, contenidoDirectorio + iAux, 1);
								printfCUCA("          --> Modo: [%d]\n", modo);
								iAux += 1;
								if ((iAux + longNombre) <= size) {
									char* nombreAux = malloc(longNombre + 1);
									memset(nombreAux, '\0', longNombre + 1);
									memcpy(nombreAux, contenidoDirectorio + iAux, longNombre);
									printfCUCA("              --> Nombre: [%s]\n", nombreAux);
									iAux += longNombre;
									encolarNombreDirOArch(&colaNombresFte, &colaNombresFin, nombreAux);
									div_t division = div(longRegistro, 4);
									i += division.quot * 4;
									if (division.rem != 0) {
										i += 4;
									}
								}
							}
						}
					} else {
						i += 4;
					}
				}
			} else {
				i += 4;
			}
		} else {
			//esta entrada de directorio esta vacia
			i += 4;
		}
	}
	return colaNombresFte;
}

int32_t leerDirectorio(char* path, off_t offset, nodoNombreDirOArch_t** nombresFte) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Leer directorio - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("READDIR - %s\n", path);
	inodeStructure_t inodoDir;
	uint8_t numBlockGroup;
	uint32_t numInodo;
//printfCUCA("Obtengo el inodo del directorio.\n");
	uint8_t error = obtenerInodoPath(path, &inodoDir, &numBlockGroup, &numInodo);
	if (!error) {
		//printfCUCA("Voy a leer el directorio.\n");
		char* contenidoDirectorio = leerIndireccionamiento(numBlockGroup, inodoDir, offset, (inodoDir.size - offset));
		*nombresFte = parsearDirectorio(contenidoDirectorio, inodoDir.size - offset);
		//desbloqueo el inodo utilizado
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
		return 0; //EN CASO DE EXITO DEVUELVE 0
	} else {
		return -ENOENT; //NO EXISTE EL DIRECTORIO
	}
}

//----------------------------------------------------------------------------------------------------
//CREACION DE UN DIRECTORIO
//----------------------------------------------------------------------------------------------------

uint8_t hayLugarEnDirectorio(uint8_t cantBytesNecesarios, char* contenidoDirectorio, uint64_t size, uint64_t* punteroALugarEncontrado) {
	printfCUCA("> Voy a chequear que haya lugar en el directorio para ingresar una entrada de [%d] bytes\n", cantBytesNecesarios);
	uint64_t i;
	uint64_t ptrLugarVacio;
	for (i = 0; i < size;) {
		if ((i + 4) <= size) {
			printfCUCA("  --> Leo el numero de i-nodo en la posición (byte) [%d]\n", (uint32_t) i);
			uint32_t numInodo;
			memcpy(&numInodo, contenidoDirectorio + i, 4);
			printfCUCA("      --> El numero de i-nodo es [%d]\n", numInodo);
			if (numInodo == 0) {
				printfCUCA("          --> Este espacio esta vacío\n");
				//este espacio esta vacio
				ptrLugarVacio = i;
				uint64_t cantBloquesDe4Vacios = 1;
				uint8_t seguirContando = 1;
				i += 4;
				while (i < size && seguirContando) {
					memcpy(&numInodo, contenidoDirectorio + i, 4);
					if (numInodo == 0) {
						printfCUCA("              --> El espacio [%d] también está vacío\n", (uint32_t) i);
						//este espacio tambien esta vacio
						cantBloquesDe4Vacios++;
						i += 4;
					} else {
						printfCUCA("              --> El espacio [%d] no está vacío\n", (uint32_t) i);
						seguirContando = 0;
					}
				}
				uint64_t cantBytesDisponibles = cantBloquesDe4Vacios * 4;
				printfCUCA("          --> Hay [%d] bytes disponibles\n", (uint32_t) cantBytesDisponibles);
				if (cantBytesDisponibles >= cantBytesNecesarios) {
					printfCUCA("              --> Encontré la cantidad de espacio vacío necesario.\n");
					*punteroALugarEncontrado = ptrLugarVacio;
					return 1;
				}
			} else {
				printfCUCA("          --> Este espacio no está vacío\n");
				if ((i + 6) <= size) {
					uint16_t longRegistro;
					memcpy(&longRegistro, contenidoDirectorio + i + 4, 2);
					printfCUCA("              --> Hay un registro de longitud [%d]\n", longRegistro);
					div_t division = div(longRegistro, 4);
					if (division.rem == 0) {
						i += division.quot * 4;
					} else {
						i += (division.quot + 1) * 4;
					}
				}
			}
		}
	}
	return 0;
}

uint8_t agregarEstructuraADirectorio(char* contenidoDirectorio, uint64_t size, uint32_t numInodoItem, uint8_t modoItem, char* nombreItem) {
	/*uint8_t cantBytesNecesarios = 4 + 2 + 1 + 1 + strlen(nombreItem);
	 uint64_t puntero;
	 uint8_t hayLugar = hayLugarEnDirectorio(cantBytesNecesarios, contenidoDirectorio, size, &puntero);
	 if (hayLugar) {
	 printfCUCA("> Hay lugar en el directorio para ingresar la entrada\n");
	 printfCUCA("> Puntero: [%d]\n", (uint32_t) puntero);
	 printfCUCA("> Número de i-nodo: [%d]\n", numInodo);
	 memcpy(contenidoDirectorio + puntero, &numInodo, 4);
	 uint16_t longitudDeRegistro = cantBytesNecesarios;
	 div_t division = div(longitudDeRegistro, 4);
	 if (division.rem != 0) {
	 longitudDeRegistro = (division.quot + 1) * 4;
	 }
	 printfCUCA("> Longitud del registro: [%d]\n", longitudDeRegistro);
	 memcpy(contenidoDirectorio + puntero + 4, &longitudDeRegistro, 2);
	 uint8_t longNombre = strlen(nombreItem);
	 printfCUCA("> Longitud del nombre: [%d]\n", longNombre);
	 memcpy(contenidoDirectorio + puntero + 4 + 2, &longNombre, 1);
	 printfCUCA("> Modo: [%d]\n", modo);
	 memcpy(contenidoDirectorio + puntero + 4 + 2 + 1, &modo, 1);
	 printfCUCA("> Nombre: [%s]\n", nombreItem);
	 memcpy(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, nombreItem, strlen(nombreItem));
	 return 0;
	 } else {
	 return -1;
	 }*/
	uint8_t longNombreItem = strlen(nombreItem);
	uint16_t longRegistroItem = 4 + 2 + 1 + 1 + longNombreItem;
	if ((longRegistroItem % 4) != 0) {
		//la longitud del registro no es multiplo de 4, redondeo hacia arriba la longitud del nombre
		longRegistroItem = ((longRegistroItem / 4) * 4) + 4;
	}
	uint64_t puntero;
	uint8_t itemGuardado = 0;
	for (puntero = 0; puntero < size && !itemGuardado;) {
		uint32_t numInodo;
		memcpy(&numInodo, contenidoDirectorio + puntero, 4);
		uint16_t longRegistro;
		memcpy(&longRegistro, contenidoDirectorio + puntero + 4, 2);
		uint8_t longNombre;
		memcpy(&longNombre, contenidoDirectorio + puntero + 4 + 2, 1);
		uint8_t modo;
		memcpy(&modo, contenidoDirectorio + puntero + 4 + 2 + 1, 1);
		/*char* nombreAux = malloc(longNombre + 1);
		 memset(nombreAux, '\0', longNombre + 1);
		 memcpy(nombreAux, contenidoDirectorio + puntero, longNombre);*/
		uint16_t longRegistroAux = 4 + 2 + 1 + 1 + longNombre;
		if ((longRegistroAux % 4) != 0) {
			//la longitud del registro no es multiplo de 4, redondeo hacia arriba la longitud del nombre
			longRegistroAux = ((longRegistroAux / 4) * 4) + 4;
		}
		if (longRegistroAux != longRegistro) {
			//hay lugar de sobra
			uint16_t longSobra = longRegistro - longRegistroAux;
			if (longSobra >= longRegistroItem) {
				//hay lugar para el item
				//modifico el espacio original
				longRegistro = longRegistroAux;
				memcpy(contenidoDirectorio + puntero + 4, &longRegistro, 2);
				//modifico el puntero
				puntero += longRegistroAux;
				memcpy(contenidoDirectorio + puntero, &numInodoItem, 4);
				memcpy(contenidoDirectorio + puntero + 4, &longSobra, 2);
				memcpy(contenidoDirectorio + puntero + 4 + 2, &longNombreItem, 1);
				memcpy(contenidoDirectorio + puntero + 4 + 2 + 1, &modoItem, 1);
				memset(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, '\0', longSobra - (4 + 2 + 1 + 1));
				memcpy(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, nombreItem, longNombreItem);
				itemGuardado = 1;
			}
		}
		puntero += longRegistro;
	}
	if (itemGuardado) {
		return 0;
	} else {
		return 1;
	}
}

/*int32_t agregarItemADirectorio(char* pathDir, char* nombreItem, mode_t modo) {
 //TODO
 printfCUCA("> Se ingresará el item [%s] al directorio [%s]\n", nombreItem, pathDir);
 uint8_t esDir;
 if (modo == ENTRADA_DIRECTORIO_TIPO_DIRECTORIO) {
 printfCUCA("  --> El tipo de la entrada debe ser de directorio\n");
 esDir = 1;
 } else {
 printfCUCA("  --> El tipo de la entrada debe ser de archivo regular\n");
 esDir = 0;
 }
 //chequear que el modo sea archivo o directorio solamente
 inodeStructure_t inodoDir;
 uint8_t numeroDeGrupoDeBloques;
 uint32_t numInodoDir;
 //obtener el inodo del directorio dentro del que se quiere crear el item
 uint8_t error = obtenerInodoPath(pathDir, &inodoDir, &numeroDeGrupoDeBloques, &numInodoDir);
 printfCUCA("  --> El size del directorio es [%d].\n", (uint32_t) inodoDir.size);
 if (!error) {
 printfCUCA("      --> Obtuve el inodo del directorio en el que ingresar la entrada.\n");
 //buscar un espacio libre
 uint8_t numBlockGroupInodoItem; //TODO comprobar que este bien el numero de inodo, o hay que sumarle 1, o se le suma 1 solo al escribirlo en la entrada de directorio
 int64_t numInodoItem = buscarYOcuparInodoLibreGlobal(&numBlockGroupInodoItem, esDir);
 if (numInodoItem >= 0) {
 printfCUCA("          --> Se ocupa el inodo [%d].", (uint32_t) numInodoItem);
 //escribir los datos en un inodo y guardarlo
 inodeStructure_t inodoItem = INODE_STRUCTURE_VACIA;
 if (esDir) {
 inodoItem.mode = INODO_MODO_DIRECTORIO;
 inodoItem.linksCount = 2; //uno por el direccionamiento dentro de este directorio y otro por el direccionamiento de "."
 //error = agregarOLiberarBloquesAInodo(numBlockGroupInodoItem, &inodoItem, staticSuperBlock.blockSize, 1);
 //if (!error) {
 //agrego al directorio las entradas "." y ".."
 // agregarEntradasPrincipalesADirectorio(inodoItem); //TODO
 //} else {
 //no hay un bloque vacio para este directorio
 //liberarInodoOcupado(numBlockGroupInodoItem, numInodoItem, esDir);
 // return -ENOSPC;
 // }
 } else {
 inodoItem.mode = INODO_MODO_ARCHIVO_REGULAR;
 inodoItem.linksCount = 1;
 }
 escribirInodo(inodoItem, numInodoItem);
 //leer el directorio completo
 char* contenidoDir = leerIndireccionamiento(numeroDeGrupoDeBloques, inodoDir, 0, inodoDir.size);
 error = agregarEstructuraADirectorio(contenidoDir, inodoDir.size, numInodoItem + 1, modo, nombreItem); //TODO COMPROBAR EL + 1
 if (error) {
 printfCUCA("          --> No hay suficiente espacio en el directorio.\n");
 //si no hay espacio truncarlo a un bloque mas y hacer todo de nuevo
 int32_t res = truncar(pathDir, inodoDir.size + staticSuperBlock.blockSize);
 if (res == 0) { //TODO reemplazar por el valor correcto de truncate
 inodoDir = leerInodo(numInodoDir + (numeroDeGrupoDeBloques * staticSuperBlock.inodesPerGroup));
 if (esDir) {
 inodoDir.linksCount++; //por la entrada ".." del subdirectorio
 }
 free(contenidoDir);
 contenidoDir = leerIndireccionamiento(numeroDeGrupoDeBloques, inodoDir, 0, inodoDir.size);
 //busco un lugar y escribo la entrada de directorio del item
 error = agregarEstructuraADirectorio(contenidoDir, inodoDir.size, numInodoItem + 1, modo, nombreItem);
 if (error) {
 return -ENOSPC; //TODO NO HAY SUFICIENTE ESPACIO, PODRIA SER REEMPLAZADO POR UN ERROR MEJOR
 }
 } else {
 //no se puede agregar la entrada
 free(contenidoDir);
 liberarInodoOcupado(numBlockGroupInodoItem, numInodoItem, esDir);
 return -ENOSPC; //NO HAY SUFICIENTE ESPACIO
 }
 }
 //escribir los datos en el directorio y guardarlo
 escribirIndireccionamiento(numeroDeGrupoDeBloques, inodoDir, inodoDir.size, 0, contenidoDir);
 free(contenidoDir);
 return 0; //EN CASO DE EXITO SE DEVUELVE 0
 } else {
 //no hay un inodo vacio
 return -ENOSPC; //NO HAY SUFICIENTE ESPACIO
 }

 } else {
 return -ENOENT; //NO EXISTE EL DIRECTORIO
 }
 }*/

void agrandarDirectorio(char* contenidoDirectorio, size_t size) {
	uint64_t puntero;
	for (puntero = 0; puntero < size;) {
		printfCUCA("for1.\n");
		uint32_t numInodo;
		memcpy(&numInodo, contenidoDirectorio + puntero, 4);
		uint16_t longRegistro;
		memcpy(&longRegistro, contenidoDirectorio + puntero + 4, 2);
		uint8_t longNombre;
		memcpy(&longNombre, contenidoDirectorio + puntero + 4 + 2, 1);
		uint8_t modo;
		memcpy(&modo, contenidoDirectorio + puntero + 4 + 2 + 1, 1);
		if ((puntero + longRegistro + staticSuperBlock.blockSize) == size) {
			printfCUCA("---------->ENCONTRADO LA ULTIMA ENTRADA DE DIRECTORIO<----------\n");
			//es el ultimoRegistro
			longRegistro += staticSuperBlock.blockSize;
			memcpy(contenidoDirectorio + puntero + 4, &longRegistro, 2);
		}
		puntero += longRegistro;
	}
}

void agregarEntradasPrincipalesADirectorio(uint8_t numBlockGroup, inodeStructure_t inodoItem, uint32_t numInodoSubDir, uint32_t numInodoDir) {
	char* contenidoDirectorio = leerIndireccionamiento(numBlockGroup, inodoItem, 0, inodoItem.size);
	uint8_t puntero = 0;
	uint16_t longRegistro = 12;
	uint8_t longNombre = 1;
	uint8_t modo = ENTRADA_DIRECTORIO_TIPO_DIRECTORIO;
	memcpy(contenidoDirectorio + puntero, &numInodoSubDir, 4);
	memcpy(contenidoDirectorio + puntero + 4, &longRegistro, 2);
	memcpy(contenidoDirectorio + puntero + 4 + 2, &longNombre, 1);
	memcpy(contenidoDirectorio + puntero + 4 + 2 + 1, &modo, 1);
	memset(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, '\0', 4);
	strcpy(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, ".");

	puntero += 12;
	longNombre = 2;
	longRegistro = staticSuperBlock.blockSize - longRegistro;
	memcpy(contenidoDirectorio + puntero, &numInodoDir, 4);
	memcpy(contenidoDirectorio + puntero + 4, &longRegistro, 2);
	memcpy(contenidoDirectorio + puntero + 4 + 2, &longNombre, 1);
	memcpy(contenidoDirectorio + puntero + 4 + 2 + 1, &modo, 1);
	memset(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, '\0', 4);
	strcpy(contenidoDirectorio + puntero + 4 + 2 + 1 + 1, "..");

	escribirIndireccionamiento(numBlockGroup, inodoItem, inodoItem.size, 0, contenidoDirectorio);

	free(contenidoDirectorio);
}

int32_t crearDirectorio(char* path, mode_t modo) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Crear directorio - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("MKDIR - %s - %d\n", path, (uint32_t) modo);
//parsear el path para obtener el path del directorio en el que se quiere crear el directorio
	//attrDirArch_t attr;
	//int32_t res = obtenerAtributos(path, &attr);
	inodeStructure_t inodoAux;
	uint8_t numBlockGroupAux;
	uint32_t numInodoAux;
	uint8_t error = obtenerInodoPath(path, &inodoAux, &numBlockGroupAux, &numInodoAux);
	if (error != 0) {
		//si no existe no esta bloqueado el inodo
		//NO HAY NINGUN ARCHIVO/DIRECTORIO CON ESTE NOMBRE
		char* pathDeDirectorio = obtenerPathDeDirectorio(path);
		char* nombreDirectorio = obtenerNombre(path);
		//res = agregarItemADirectorio(pathDeDirectorio, nombreDirectorio, ENTRADA_DIRECTORIO_TIPO_DIRECTORIO);
		inodeStructure_t inodoDir;
		uint8_t numBlockGroupDir;
		uint32_t numInodoDir;
		uint8_t error = obtenerInodoPath(pathDeDirectorio, &inodoDir, &numBlockGroupDir, &numInodoDir);
		printfCUCA("<crearDirectorio> numBlockGroupDir: %d\n", numBlockGroupDir);
		int32_t res;
		if (!error) {
			inodoDir.linksCount++; //por la entrada ".." del subdirectorio
			uint8_t numBlockGroupItem; //TODO comprobar que este bien el numero de inodo, o hay que sumarle 1, o se le suma 1 solo al escribirlo en la entrada de directorio
			int64_t numInodoItemAux = buscarYOcuparInodoLibreGlobal(&numBlockGroupItem, 1);
			if (numInodoItemAux >= 0) {
				uint32_t numInodoItem = (uint32_t) numInodoItemAux;
				//bloqueo el inodo del directorio creado
				/*TODO*/empiezoATrabajarEnInodo(numInodoItem, 1);
				inodeStructure_t inodoItem = INODE_STRUCTURE_VACIA;
				inodoItem.mode = INODO_MODO_DIRECTORIO;
				inodoItem.linksCount = 2; //uno por el direccionamiento dentro de este directorio y otro por el direccionamiento de "."
				escribirInodo(inodoItem, numInodoItem);
				//leo el directorio
				char* contenidoDirectorio = leerIndireccionamiento(numBlockGroupDir, inodoDir, 0, inodoDir.size);
				error = agregarEstructuraADirectorio(contenidoDirectorio, inodoDir.size, numInodoItem + 1, ENTRADA_DIRECTORIO_TIPO_DIRECTORIO, nombreDirectorio); //TODO COMPROBAR EL + 1
				if (!error) {
					escribirIndireccionamiento(numBlockGroupDir, inodoDir, inodoDir.size, 0, contenidoDirectorio);
					res = 0;
				} else {
					printfCUCA("No hay suficiente espacio, hay que truncar.\n");
					//no hay espacio, es necesario truncar
					//int32_t resTruncar = truncar(pathDeDirectorio, inodoDir.size + staticSuperBlock.blockSize);
					int32_t resTruncar = truncarInodo(numInodoDir, numBlockGroupDir, &inodoDir, inodoDir.size + staticSuperBlock.blockSize);
					if (resTruncar == 0) {
						printfCUCA("Ya trunque.\n");
						free(contenidoDirectorio);
						//obtenerInodoPath(pathDeDirectorio, &inodoDir, &numBlockGroupDir, &numInodoDir);
						inodoDir.linksCount++; //el que esta hecho arriba se piso con la nueva lectura del inodo
						char* contenidoDirectorio = leerIndireccionamiento(numBlockGroupDir, inodoDir, 0, inodoDir.size);
						agrandarDirectorio(contenidoDirectorio, inodoDir.size);
						agregarEstructuraADirectorio(contenidoDirectorio, inodoDir.size, numInodoItem + 1, ENTRADA_DIRECTORIO_TIPO_DIRECTORIO, nombreDirectorio);
						escribirIndireccionamiento(numBlockGroupDir, inodoDir, inodoDir.size, 0, contenidoDirectorio);
						res = 0;
					} else {
						liberarInodoOcupado(numBlockGroupItem, numInodoItem, 1);
						res = resTruncar;
					}
				}
				if (res == 0) {
					escribirInodo(inodoDir, numInodoDir);
					//agrego los subdirectorios "." y ".."
					//int32_t resTruncar = truncar(path, staticSuperBlock.blockSize);
					int32_t resTruncar = truncarInodo(numInodoItem, numBlockGroupItem, &inodoItem, staticSuperBlock.blockSize);
					if (resTruncar == 0) {
						//obtenerInodoPath(path, &inodoItem, &numBlockGroupItem, &numInodoItem);
						agregarEntradasPrincipalesADirectorio(numBlockGroupItem, inodoItem, numInodoItem + 1, numInodoDir + 1);
						escribirInodo(inodoItem, numInodoItem);
					} else {
						//habria que chequear tambien de liberar el
						liberarInodoOcupado(numBlockGroupItem, numInodoItem, 1);
						res = resTruncar;
					}
				}
				free(contenidoDirectorio);
			} else {
				res = -ENOSPC;
			}
			//desbloqueo el archivo, si no existe no esta bloqueado
			/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
		} else {
			res = -ENOENT;
		}
		free(pathDeDirectorio);
		free(nombreDirectorio);
		return res;
	} else {
		//desbloqueo el archivo, si no existe no esta bloqueado
		/*TODO*/dejoDeTrabajarEnInodo(numInodoAux);
		return -EEXIST; //TODO REVISAR SI SE PUEDE REEMPLAZAR POR OTRO ERROR, EL DIRECTORIO YA EXISTE
	}
}

//----------------------------------------------------------------------------------------------------
//BORRADO DE UN DIRECTORIO
//----------------------------------------------------------------------------------------------------

uint8_t borrarEstructuraDeDirectorio(char* contenidoDir, uint32_t size, directoryEntry_t* entradaDirectorio) {
	/*uint64_t i;
	 uint8_t encontrado = 0;
	 for (i = 0; i < size && !encontrado;) {
	 uint64_t iAux = i;
	 if ((iAux + 4) <= size) {
	 uint32_t numInodoAux;
	 memcpy(&numInodoAux, contenidoDir + i, 4);
	 printfCUCA("Numero de Inodo: [%d].\n", numInodoAux);
	 if (numInodoAux > 0) {
	 iAux += 4;
	 if ((iAux + 2) <= size) {
	 uint16_t longRegistro;
	 memcpy(&longRegistro, contenidoDir + iAux, 2);
	 if (longRegistro > 0) {
	 printfCUCA("-Longitud del Registro: [%d].\n", longRegistro);
	 iAux += 2;
	 if ((iAux + 1) <= size) {
	 uint8_t longNombre;
	 memcpy(&longNombre, contenidoDir + iAux, 1);
	 printfCUCA("--Longitud del Nombre: [%d].\n", longNombre);
	 iAux += 1;
	 if ((iAux + 1) <= size) {
	 uint8_t modo;
	 memcpy(&modo, contenidoDir + iAux, 1);
	 printfCUCA("---Modo: [%d].\n", modo);
	 iAux += 1;
	 if ((iAux + longNombre) <= size) {
	 char* nombreAux = malloc(longNombre + 1);
	 memset(nombreAux, '\0', longNombre + 1);
	 memcpy(nombreAux, contenidoDir + iAux, longNombre);
	 printfCUCA("----Nombre: [%s].\n", nombreAux);
	 if (strcmp(nombreAux, (*entradaDirectorio).name) == 0) {
	 printfCUCA("-----Lo encontre!!!.\n");
	 (*entradaDirectorio).inode = numInodoAux - 1; //para que el primer inodo sea el 0 y no el 1
	 (*entradaDirectorio).recLen = longRegistro;
	 (*entradaDirectorio).nameLen = longNombre;
	 (*entradaDirectorio).fileType = modo;
	 encontrado = 1;
	 div_t division = div(longRegistro, 4);
	 uint8_t cantBytesABorrar = division.quot * 4;
	 if (division.rem != 0) {
	 cantBytesABorrar += 4;
	 }
	 //TODO ESTA ESCRIBIENDO BASURA
	 memset(contenidoDir + i, '\0', cantBytesABorrar);
	 }
	 iAux += longNombre;
	 div_t division = div(longRegistro, 4);
	 i += division.quot * 4;
	 if (division.rem != 0) {
	 i += 4;
	 }
	 }
	 }
	 }
	 } else {
	 i += 4;
	 }
	 }
	 }
	 } else {
	 //esta entrada de directorio esta vacia
	 i += 4;
	 }
	 }
	 return encontrado;*/
	uint32_t puntero, punteroAnt;
	uint8_t borrado = 0;
	for (puntero = 0, punteroAnt = 0; puntero < size && !borrado;) {
		printfCUCA("Leo una entrada.\n");
		uint32_t numInodo;
		memcpy(&numInodo, contenidoDir + puntero, 4);
		printf("Numero de Inodo: %d.\n", numInodo);
		uint16_t longRegistro;
		memcpy(&longRegistro, contenidoDir + puntero + 4, 2);
		printfCUCA("Longitud de Registro: %d.\n", longRegistro);
		uint8_t longNombre;
		memcpy(&longNombre, contenidoDir + puntero + 4 + 2, 1);
		printfCUCA("Longitud de Nombre: %d.\n", longNombre);
		uint8_t modo;
		memcpy(&modo, contenidoDir + puntero + 4 + 2 + 1, 1);
		printfCUCA("Modo: %d.\n", modo);
		char* nombreAux = malloc(longNombre + 1);
		memset(nombreAux, '\0', longNombre + 1);
		memcpy(nombreAux, contenidoDir + puntero + 4 + 2 + 1 + 1, longNombre);
		printf("Nombre: %s", nombreAux);
		if (strcmp(nombreAux, (*entradaDirectorio).name) == 0) {
			printf("Es la entrada buscada.\n");
			//es la entrada buscada
			(*entradaDirectorio).inode = numInodo;
			(*entradaDirectorio).recLen = longRegistro;
			(*entradaDirectorio).nameLen = longNombre;
			(*entradaDirectorio).fileType = modo;
			uint16_t longRegistroAnt;
			memcpy(&longRegistroAnt, contenidoDir + punteroAnt + 4, 2);
			longRegistroAnt += longRegistro;
			memcpy(contenidoDir + punteroAnt + 4, &longRegistroAnt, 2);
			borrado = 1;
		}
		punteroAnt = puntero;
		puntero += longRegistro;
	}
	return borrado;
}

uint8_t estaVacioDirectorio(uint8_t numBlockGroup, inodeStructure_t inodoDir) {
	if (inodoDir.size == 0) {
		printfCUCA("Tamaño: 0\n");
		return 1;
	} else {
		char* contenidoDir = leerIndireccionamiento(numBlockGroup, inodoDir, 0, inodoDir.size);
		uint8_t cantIteraciones;
		uint64_t i;
		for (i = 0, cantIteraciones = 0; i < inodoDir.size; cantIteraciones++) {
			uint16_t longRegistro;
			memcpy(&longRegistro, contenidoDir + i + 4, 2);
			i += longRegistro;
		}
		if (cantIteraciones == 2) {
			// solo estan "." y ".."
			return 1;
		} else {
			return 0;
		}
	}
}

int32_t borrarItemDeDirectorio(inodeStructure_t inodoDir, uint8_t numBlockGroupDir, uint32_t numInodoDir, inodeStructure_t inodoItem, char* nombreItem) {
//TODO REVISAR
	uint8_t esDir;
//obtener el inodo del directorio dentro del que se quiere crear el item

	char* contenidoDir = leerIndireccionamiento(numBlockGroupDir, inodoDir, 0, inodoDir.size);
	directoryEntry_t entradaDirectorio;
	entradaDirectorio.name = malloc(strlen(nombreItem) + 1);
	memcpy(entradaDirectorio.name, nombreItem, strlen(nombreItem) + 1);
	uint8_t borrado = borrarEstructuraDeDirectorio(contenidoDir, inodoDir.size, &entradaDirectorio);
	if (borrado) {
		entradaDirectorio.inode--; //TODO CHEQUEAR QUE ESTE BIEN
		printf("<borrarItemDeDirectorio> entradaDirectorio.inode %d\n", entradaDirectorio.inode);
		printf("<borrarItemDeDirectorio> entradaDirectorio.fileType %d\n", entradaDirectorio.fileType);
		printf("<borrarItemDeDirectorio> entradaDirectorio.name %s\n", entradaDirectorio.name);
		if (entradaDirectorio.fileType == ENTRADA_DIRECTORIO_TIPO_DIRECTORIO || entradaDirectorio.fileType == ENTRADA_DIRECTORIO_TIPO_ARCHIVO_REGULAR) {
			if (entradaDirectorio.fileType == ENTRADA_DIRECTORIO_TIPO_DIRECTORIO) {
				printf("Es directorio\n");
				esDir = 1;
			} else {
				printf("Es archivo regular\n");
				esDir = 0;
			}
			uint8_t numBlockGroupVictima = div(entradaDirectorio.inode, staticSuperBlock.inodesPerGroup).quot;
			printf("<borrarItemDeDirectorio> numBlockGroupVictima %d\n", numBlockGroupVictima);
			uint32_t numInodoRelativoVictima = div(entradaDirectorio.inode, staticSuperBlock.inodesPerGroup).rem;
			printf("<borrarItemDeDirectorio> numInodoRelativoVictima %d\n", numInodoRelativoVictima);
			if (esDir) {
				inodoDir.linksCount--; //por la entrada ".." del subdirectorio
				inodeStructure_t inodoItem = leerInodo(entradaDirectorio.inode);
				uint8_t estaVacio = estaVacioDirectorio(numBlockGroupVictima, inodoItem);
				if (!estaVacio) {
					printfCUCA("No está vacio\n");
					free(contenidoDir);
					free(entradaDirectorio.name);
					return -ENOTEMPTY; //EL DIRECTORIO NO ESTA VACIO
				} else {
					printfCUCA("Está vacío\n");
					printf("<borrarItemDeDirectorio> numInodoDir %d\n", numInodoDir);
					escribirInodo(inodoDir, numInodoDir);
				}
			}
			//concatenarDosPaths(&pathDir, nombreItem);
			truncarInodo(entradaDirectorio.inode, numBlockGroupVictima, &inodoItem, 0);
			liberarInodoOcupado(numBlockGroupVictima, numInodoRelativoVictima, esDir);
			escribirIndireccionamiento(numBlockGroupDir, inodoDir, inodoDir.size, 0, contenidoDir);
			free(contenidoDir);
			free(entradaDirectorio.name);
			return 0; //EN CASO DE EXITO DEVUELVE 0
		} else {
			free(contenidoDir);
			free(entradaDirectorio.name);
			return -EPERM;
		}
	} else {
		//no se pudo encontrar la entrada de directorio
		free(contenidoDir);
		free(entradaDirectorio.name);
		return -ENOENT; //NO EXISTE EL DIRECTORIO/ARCHIVO A BORRAR
	}
}

int32_t borrarDirectorio(char* path) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Borrar directorio - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("RMDIR - %s\n", path);
	/*//TODO
	 attrDirArch_t atributos;
	 if (obtenerAtributos(path, &atributos) == 0) {
	 truncar(path, 0);
	 inodeStructure_t inodoBuscado;
	 uint8_t numeroDeGrupoDeBloque;
	 uint32_t numeroDeInodo;
	 if (obtenerInodoPath(path, &inodoBuscado, &numeroDeGrupoDeBloque, &numeroDeInodo) == 0) {
	 liberarInodoOcupado(numeroDeGrupoDeBloque, numeroDeInodo, 1);
	 printfCUCA("Directorio borrado\n");
	 return 0;
	 }
	 }
	 printfCUCA("el directorio no se encuentra vacio\n");
	 return -1;
	 //chequear que el directorio este vacio
	 //liberar el inodo
	 //eliminarlo del directorio al que pertenece
	 //reemplazar por lo que haya que devolver*/
	char* pathDeDirectorio = obtenerPathDeDirectorio(path);
	char* nombreDirectorio = obtenerNombre(path);
	inodeStructure_t inodoDir;
	uint8_t numBlockGroupDir;
	uint32_t numInodoDir;
	uint8_t error = obtenerInodoPath(pathDeDirectorio, &inodoDir, &numBlockGroupDir, &numInodoDir);
	if (!error) {
		inodeStructure_t inodoSubDir;
		uint8_t numBlockGroupSubDir;
		uint32_t numInodoSubDir;
		uint8_t error = obtenerInodoPath(path, &inodoSubDir, &numBlockGroupSubDir, &numInodoSubDir);
		if (error == 0 && (inodoSubDir.mode & S_IFDIR)) {
			int32_t res;
			if (strcmp(nombreDirectorio, ".") != 0 && strcmp(nombreDirectorio, "..") != 0) {
				res = borrarItemDeDirectorio(inodoDir, numBlockGroupDir, numInodoDir, inodoSubDir, nombreDirectorio);
			} else {
				res = -EPERM; //TODO REVISAR SI HAY UN MEJOR ERROR
			}
			free(pathDeDirectorio);
			free(nombreDirectorio);
			//desbloqueo el archivo, si no existe no esta bloqueado
			/*TODO*/dejoDeTrabajarEnInodo(numInodoSubDir);
			//desbloqueo el inodo
			/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
			return res;
		} else if (error == 0) {
			//desbloqueo el archivo, si no existe no esta bloqueado
			/*TODO*/dejoDeTrabajarEnInodo(numInodoSubDir);
			//desbloqueo el inodo
			/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
			return -ENOENT;
		} else {
			//desbloqueo el inodo
			/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
			return -ENOENT;
		}
	} else {
		return -ENOENT;
	}
}

//----------------------------------------------------------------------------------------------------
//CREACION DE UN ARCHIVO
//----------------------------------------------------------------------------------------------------

int32_t crearArchivo(char* path, mode_t modo) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Crear Archivo - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("CREATE FILE - %s - %d\n", path, (uint32_t) modo);
	inodeStructure_t inodoAux;
	uint8_t numBlockGroupAux;
	uint32_t numInodoAux;
	uint8_t error = obtenerInodoPath(path, &inodoAux, &numBlockGroupAux, &numInodoAux);
	if (error != 0) {
		//NO HAY NINGUN ARCHIVO/DIRECTORIO CON ESTE NOMBRE
		char* pathDeDirectorio = obtenerPathDeDirectorio(path);
		char* nombreArchivo = obtenerNombre(path);
		//res = agregarItemADirectorio(pathDeDirectorio, nombreDirectorio, ENTRADA_DIRECTORIO_TIPO_DIRECTORIO);
		inodeStructure_t inodoDir;
		uint8_t numBlockGroupDir;
		uint32_t numInodoDir;
		uint8_t error = obtenerInodoPath(pathDeDirectorio, &inodoDir, &numBlockGroupDir, &numInodoDir);
		int32_t res;
		if (!error) {
			uint8_t numBlockGroupItem; //TODO comprobar que este bien el numero de inodo, o hay que sumarle 1, o se le suma 1 solo al escribirlo en la entrada de directorio
			int64_t numInodoItemAux = buscarYOcuparInodoLibreGlobal(&numBlockGroupItem, 0);
			if (numInodoItemAux >= 0) {
				uint32_t numInodoItem = (uint32_t) numInodoItemAux;
				inodeStructure_t inodoItem = INODE_STRUCTURE_VACIA;
				inodoItem.mode = INODO_MODO_ARCHIVO_REGULAR;
				inodoItem.linksCount = 1; //por el direccionamiento dentro de este directorio
				escribirInodo(inodoItem, numInodoItem);
				//leo el directorio
				char* contenidoDirectorio = leerIndireccionamiento(numBlockGroupDir, inodoDir, 0, inodoDir.size);
				error = agregarEstructuraADirectorio(contenidoDirectorio, inodoDir.size, numInodoItem + 1, ENTRADA_DIRECTORIO_TIPO_ARCHIVO_REGULAR, nombreArchivo); //TODO COMPROBAR EL + 1
				if (!error) {
					escribirIndireccionamiento(numBlockGroupDir, inodoDir, inodoDir.size, 0, contenidoDirectorio);
					res = 0;
				} else {
					//no hay espacio, es necesario truncar
					//int32_t resTruncar = truncar(pathDeDirectorio, inodoDir.size + staticSuperBlock.blockSize);
					int32_t resTruncar = truncarInodo(numInodoDir, numBlockGroupDir, &inodoDir, inodoDir.size + staticSuperBlock.blockSize);
					if (resTruncar == 0) {
						free(contenidoDirectorio);
						//obtenerInodoPath(pathDeDirectorio, &inodoDir, &numBlockGroupDir, &numInodoDir);
						char* contenidoDirectorio = leerIndireccionamiento(numBlockGroupDir, inodoDir, 0, inodoDir.size);
						agrandarDirectorio(contenidoDirectorio, inodoDir.size);
						agregarEstructuraADirectorio(contenidoDirectorio, inodoDir.size, numInodoItem + 1, ENTRADA_DIRECTORIO_TIPO_ARCHIVO_REGULAR, nombreArchivo);
						escribirIndireccionamiento(numBlockGroupDir, inodoDir, inodoDir.size, 0, contenidoDirectorio);
						res = 0;
					} else {
						liberarInodoOcupado(numBlockGroupItem, numInodoItem, 1);
						res = resTruncar;
					}
				}
				if (res == 0) {
					escribirInodo(inodoDir, numInodoDir);
				}
				free(contenidoDirectorio);
			} else {
				res = -ENOSPC;
			}
			//desbloqueo el archivo, si no existe no esta bloqueado
			/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
		} else {
			res = -ENOENT;
		}
		free(pathDeDirectorio);
		free(nombreArchivo);
		return res;
	} else {
		//desbloqueo el archivo, si no existe no esta bloqueado
		/*TODO*/dejoDeTrabajarEnInodo(numInodoAux);
		return -EEXIST; //TODO REVISAR SI SE PUEDE REEMPLAZAR POR OTRO ERROR, EL DIRECTORIO YA EXISTE
	}
}

//----------------------------------------------------------------------------------------------------
//APERTURA DE UN ARCHIVO
//----------------------------------------------------------------------------------------------------

uint8_t existeEnFileList(char *path) {
	nodoFileList_t *aux = fileList;
	uint8_t encontrado = 0;
	while ((aux != NULL) && (!encontrado)) {
		if (strcmp(aux->fileInfo.path, path) == 0) {
			encontrado = 1;
		}
		aux = aux->sig;
	}
	return encontrado;
}

void imprimirFileList(void) {
	printfCUCA("===============================================================================\n");
	printfCUCA("                             > Lista de archivos <                             \n");
	printfCUCA("-------------------------------------------------------------------------------\n");
	nodoFileList_t *aux = fileList;
	while (aux != NULL) {
		printfCUCA("> %s [IP: %s]\n", aux->fileInfo.path, aux->fileInfo.ip);
		aux = aux->sig;
	}
	free(aux);
}

void agregarEnFileList(char *path, char *ip) {
	nodoFileList_t *aux = (nodoFileList_t*) malloc(sizeof(nodoFileList_t));
	aux->fileInfo.path = (char*) malloc(strlen(path) + 1);
	aux->fileInfo.ip = (char*) malloc(strlen(ip) + 1);
	strcpy(aux->fileInfo.path, path);
	strcpy(aux->fileInfo.ip, ip);
	aux->sig = fileList;
	fileList = aux;
}

uint8_t quitarDeFileList(char *path, char *ip) {
	nodoFileList_t *aux = fileList;
	nodoFileList_t *anterior = fileList;
	if (fileList != NULL) {
		if ((strcmp(fileList->fileInfo.path, path) == 0) && (strcmp(fileList->fileInfo.ip, ip) == 0)) {
			fileList = fileList->sig;
			free(aux->fileInfo.path);
			free(aux);
			printfCUCA("Quité el path [%s] del primer nodo de la File List\n", path);
			return 1;
		} else {
			aux = aux->sig;
			while ((aux != NULL) && (strcmp(aux->fileInfo.path, path) != 0) && (strcmp(fileList->fileInfo.ip, ip) != 0)) {
				anterior = aux;
				aux = aux->sig;
				printfCUCA("Busco\n");
			}
			if ((aux != NULL) && (strcmp(aux->fileInfo.path, path) == 0) && (strcmp(fileList->fileInfo.ip, ip) == 0)) {
				anterior->sig = aux->sig;
				free(aux->fileInfo.path);
				free(aux);
				printfCUCA("Quité el path [%s]\n", path);
				return 1;
			} else {
				printfCUCA("No lo encontré, con tilde en la é\n");
				return 0;
			}
		}
	}
	printfCUCA("La FileList está vacía\n");
	return 0;
}

void cerrarArchivosDeIP(char *ip) {
	pthread_mutex_lock(&mutexFileList);
	while ((fileList != NULL) && (strcmp(fileList->fileInfo.ip, ip) == 0)) {
		nodoFileList_t *aux = fileList;
		printfCUCA("Archivo [%s] eliminado de la File List\n", aux->fileInfo.path);
		fileList = fileList->sig;
		free(aux->fileInfo.path);
		free(aux);
	}
	if ((fileList != NULL) && (fileList->sig != NULL)) {
		nodoFileList_t *anterior = fileList;
		nodoFileList_t *aux = fileList->sig;
		while (aux != NULL) {
			if (strcmp(fileList->fileInfo.ip, ip) == 0) {
				printfCUCA("Archivo [%s] eliminado de la File List\n", aux->fileInfo.path);
				nodoFileList_t *nodoEliminar = aux;
				anterior->sig = aux->sig;
				aux = aux->sig;
				anterior = anterior->sig;
				free(nodoEliminar->fileInfo.path);
				free(nodoEliminar);
			} else {
				anterior = anterior->sig;
				aux = aux->sig;
			}
		}
	}
	imprimirFileList();
	pthread_mutex_unlock(&mutexFileList);
}

int8_t permisoEscritura(mode_t modo) {
// mode is as for the system call open. (mode & O_ACCMODE) is one of O_RDONLY, O_WRONLY and O_RDWR. The mode can also contain other flags, most notably O_APPEND.
	mode_t modo_aux = modo & O_ACCMODE;
	if (modo_aux != O_RDONLY) {
		printfCUCA("Tengo permiso de escritura (%d:%d)\n", (uint32_t) modo, (uint32_t) modo_aux);
		return 1;
	} else {
		printfCUCA("No tengo permiso de escritura (%d:%d)\n", (uint32_t) modo, (uint32_t) modo_aux);
		return 0;
	}
}

int32_t abrirArchivo(char* path, mode_t modo, char* ip) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Abrir archivo - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("OPEN - %s - %d - %s\n", path, (uint32_t) modo, ip);
	inodeStructure_t inodoArch;
	uint8_t numBlockGroup;
	uint32_t numInodo;
	uint8_t error = obtenerInodoPath(path, &inodoArch, &numBlockGroup, &numInodo);
	int32_t res;
	if (!error) {
		pthread_mutex_lock(&mutexFileList);
		if (permisoEscritura(modo)) {
			if (!existeEnFileList(path)) {
				printfCUCA("Agrego el archivo %s (%s) en la File List\n", path, ip);
				agregarEnFileList(path, ip);
				res = 0;
			} else {
				printfCUCA("El archivo %s ya existe en la File List\n", path);
				res = -EPERM;
			}
		} else {
			res = 0;
		}
		pthread_mutex_unlock(&mutexFileList);
		//desbloqueo el archivo, si no existe no esta bloqueado
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
	} else {
		res = -ENOENT;
	}
	imprimirFileList();
	return res;
//return 0;
}

//----------------------------------------------------------------------------------------------------
//CIERRE DE UN ARCHIVO
//----------------------------------------------------------------------------------------------------

int32_t cerrarArchivo(char* path, mode_t modo, char* ip) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Cerrar archivo - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("CLOSE - %s - %d - %s\n", path, (uint32_t) modo, ip);
	inodeStructure_t inodoArch;
	uint8_t numBlockGroup;
	uint32_t numInodo;
	uint8_t error = obtenerInodoPath(path, &inodoArch, &numBlockGroup, &numInodo);
	int32_t res;
	if (!error) {
		if (permisoEscritura(modo)) {
			pthread_mutex_lock(&mutexFileList);
			if (quitarDeFileList(path, ip)) {
				printfCUCA("Archivo %s eliminado de la File List\n", path);
				res = 0;
			} else {
				printfCUCA("No se poseen los permisos suficientes\n");
				//res = -EPERM;
				res = 0;
			}
			pthread_mutex_unlock(&mutexFileList);
		} else {
			res = 0;
		}
		//desbloqueo el archivo, si no existe no esta bloqueado
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
	} else {
		res = -ENOENT;
	}
	return res;
//return 0;
}

//----------------------------------------------------------------------------------------------------
//LECTURA DE UN ARCHIVO
//----------------------------------------------------------------------------------------------------
int32_t leerArchivo(char* path, off_t offset, size_t size, char** contenidoArchivo) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Leer archivo- Path [%s] - Size [%d] - Offset [%d]", path, (uint32_t) size, (uint32_t) offset);
	printfCUCA("===============================================================================\n");
	printfCUCA("READ %s %d %d\n", path, (uint32_t) offset, size);
	printfCUCA("Me llego una lectura de %d bytes desde el byte %d.\n", size, (uint32_t) offset);
	inodeStructure_t inodoArch;
	uint8_t numBlockGroup;
	uint32_t numInodo;
//printfCUCA("Obtengo el inodo del archivo.\n");
	uint8_t error = obtenerInodoPath(path, &inodoArch, &numBlockGroup, &numInodo);
	if (!error) {
		if (offset > inodoArch.size) {
			//desbloqueo el archivo
			/*TODO*/dejoDeTrabajarEnInodo(numInodo);
			printfCUCA("El offset es mayor al tamanio del archivo.\n");
			//desbloqueo el archivo
			/*TODO*/dejoDeTrabajarEnInodo(numInodo);
			return 0; //TODO REVISAR SI NO HAY UN MEJOR VALOR PARA ERROR, NO PUEDO LEER NADA
		} else if (offset + size > inodoArch.size) {
			size = inodoArch.size - offset;
			printfCUCA("El size pedido es mayor al size del archivo, lo corto.\n");
		}
		printfCUCA("Voy a leer %d bytes.\n", size);
		//printfCUCA("Voy a leer el archivo.\n");
		*contenidoArchivo = leerIndireccionamiento(numBlockGroup, inodoArch, offset, size);
		//desbloqueo el archivo
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
		return size; //EN CASO DE EXITO SE DEVUELVE CUANTO SE LEYO
	} else {
		//si el archivo no existe no esta bloqueado
		return -ENOENT;
	}
}

//----------------------------------------------------------------------------------------------------
//ESCRITURA DE UN ARCHIVO
//----------------------------------------------------------------------------------------------------

int32_t escribirArchivo(char* path, size_t size, off_t offset, char* buffer) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Escribir archivo - Path [%s] - Size [%d] - Offset [%d]", path, (uint32_t) size, (uint32_t) offset);
	printfCUCA("===============================================================================\n");
	printfCUCA("WRITE - %s - %d - %d\n", path, (uint32_t) offset, size);
	inodeStructure_t inodo;
	uint8_t numBlockGroup;
	uint32_t numInodo;
	uint8_t error = obtenerInodoPath(path, &inodo, &numBlockGroup, &numInodo); //TODO REVISAR COMO BLOQUEAR ESTANDO EL TRUNCAR
	if (!error) {
		int32_t res = 0;
		if ((size + offset) > inodo.size) {
			//uint8_t resTruncar = truncar(path, (off_t) (size + offset));
			res = truncarInodo(numInodo, numBlockGroup, &inodo, size + offset);
		}
		if (res == 0) {
			escribirIndireccionamiento(numBlockGroup, inodo, size, offset, buffer);
			//desbloqueo el archivo
			/*TODO*/dejoDeTrabajarEnInodo(numInodo);
			return size;
		} else {
			//desbloqueo el archivo
			/*TODO*/dejoDeTrabajarEnInodo(numInodo);
			return res;
		}
	} else {
		//no es necesario desbloquear el inodo, si no existe no esta bloqueado
		return -ENOENT;
	}
}

//----------------------------------------------------------------------------------------------------
//BORRADO DE UN ARCHIVO
//----------------------------------------------------------------------------------------------------

int32_t borrarArchivo(char* path, char *ip) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Borrar archivo - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("DELETE - %s - %s\n", path, ip);
	/*//TODO
	 truncar(path, 0);
	 inodeStructure_t inodoBuscado;
	 uint8_t numeroDeGrupoDeBloque;
	 uint32_t numeroDeInodo;
	 if (obtenerInodoPath(path, &inodoBuscado, &numeroDeGrupoDeBloque, &numeroDeInodo) == 0) {
	 liberarInodoOcupado(numeroDeGrupoDeBloque, numeroDeInodo, 0);
	 obtenerPathDeDirectorio(path);
	 printfCUCA("archivo borrado\n");
	 return 0;
	 }

	 printfCUCA("el archivo no se encuentra\n");
	 return -ENOENT;*/
	pthread_mutex_lock(&mutexFileList);
	if (!existeEnFileList(path)) {
		agregarEnFileList(path, ip);
		pthread_mutex_unlock(&mutexFileList);
		char* pathDeDirectorio = obtenerPathDeDirectorio(path);
		char* nombreArchivo = obtenerNombre(path);
		inodeStructure_t inodoDir;
		uint8_t numBlockGroupDir;
		uint32_t numInodoDir;
		uint8_t error = obtenerInodoPath(pathDeDirectorio, &inodoDir, &numBlockGroupDir, &numInodoDir);
		if (!error) {
			inodeStructure_t inodoArchivo;
			uint8_t numBlockGroupArchivo;
			uint32_t numInodoArchivo;
			uint8_t error = obtenerInodoPath(path, &inodoArchivo, &numBlockGroupArchivo, &numInodoArchivo);
			if (error == 0 && (inodoArchivo.mode & S_IFREG)) {
				int32_t res = borrarItemDeDirectorio(inodoDir, numBlockGroupDir, numInodoDir, inodoArchivo, nombreArchivo);
				free(pathDeDirectorio);
				free(nombreArchivo);
				//desbloqueo el inodo
				/*TODO*/dejoDeTrabajarEnInodo(numInodoArchivo);
				//desbloqueo el inodo
				/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
				pthread_mutex_lock(&mutexFileList);
				quitarDeFileList(path, ip);
				pthread_mutex_unlock(&mutexFileList);
				return res;
			} else if (error == 0) {
				//desbloqueo el inodo
				/*TODO*/dejoDeTrabajarEnInodo(numInodoArchivo);
				//desbloqueo el inodo
				/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
				pthread_mutex_lock(&mutexFileList);
				quitarDeFileList(path, ip);
				pthread_mutex_unlock(&mutexFileList);
				return -EISDIR;
			} else {
				//no es necesario desbloquear el inodo, si no existe no esta bloqueado
				//desbloqueo el inodo
				/*TODO*/dejoDeTrabajarEnInodo(numInodoDir);
				pthread_mutex_lock(&mutexFileList);
				quitarDeFileList(path, ip);
				pthread_mutex_unlock(&mutexFileList);
				return -ENOENT;
			}
		} else {
			//no es necesario desbloquear el inodo, si no existe no esta bloqueado
			pthread_mutex_lock(&mutexFileList);
			quitarDeFileList(path, ip);
			pthread_mutex_unlock(&mutexFileList);
			return -ENOENT;
		}
	} else {
		pthread_mutex_unlock(&mutexFileList);
		printfCUCA("El archivo está abierto\n");
		//no es necesario desbloquear el inodo, si no existe no esta bloqueado
		return -EPERM;
	}
}

//----------------------------------------------------------------------------------------------------
//TRUNCAR UN ARCHIVO
//----------------------------------------------------------------------------------------------------

uint32_t cantBloquesNecesariosNivelN(uint64_t byteInicio, uint64_t byteFin, uint8_t nivel) {
	if (nivel > 0) {
		//div_t divInicio = div(byteInicio, maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		struct {
			uint32_t quot;
			uint32_t rem;
		} divInicio;
		divInicio.quot = byteInicio / (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		divInicio.rem = byteInicio % (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		uint64_t puntInicio = divInicio.quot;
		uint64_t offInicio = divInicio.rem;
		/*if(divInicio.rem != 0){
		 puntInicio++;
		 offInicio = 0;
		 }*/
		//div_t divFin = div(byteFin, maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		struct {
			uint32_t quot;
			uint32_t rem;
		} divFin;
		divFin.quot = byteFin / (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		divFin.rem = byteFin % (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		uint64_t puntFin = divFin.quot;
		uint64_t offFin = divFin.rem;
		if (offFin == 0 && puntFin > 0) {
			puntFin--;
			offFin = maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize - 1;
		}

		if (puntInicio == puntFin) {
			//HAY UN SOLO PUNTERO
			uint32_t cantBloques = 0;
			if (offInicio == 0) {
				cantBloques++;
			}
			cantBloques += cantBloquesNecesariosNivelN(offInicio, offFin, nivel - 1);
			return cantBloques;
		} else {
			uint64_t puntAux;
			uint32_t cantBloques = 0;
			for (puntAux = puntInicio; puntAux <= puntFin; puntAux++) {
				uint64_t offInicioAux;
				uint64_t offFinAux;
				if (puntAux == puntInicio) {
					offInicioAux = offInicio;
					offFinAux = maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize - 1;
				} else if (puntAux == puntFin) {
					offInicioAux = 0;
					offFinAux = offFin;
				} else {
					offInicioAux = 0;
					offFinAux = maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize - 1;
				}
				if (offInicioAux == 0) {
					cantBloques++;
				}
				cantBloques += cantBloquesNecesariosNivelN(offInicioAux, offFinAux, nivel - 1);
			}
			return cantBloques;
		}
	} else {
		div_t divInicio = div(byteInicio, staticSuperBlock.blockSize);
		uint64_t puntInicio = divInicio.quot;
		//uint64_t offInicio = divInicio.rem;
		if (divInicio.rem != 0) {
			puntInicio++;
			//offInicio = 0;
		}
		div_t divFin = div(byteFin, staticSuperBlock.blockSize);
		uint64_t puntFin = divFin.quot;
		uint64_t offFin = divFin.rem;
		if (offFin == 0 && puntFin > 0) {
			puntFin--;
			offFin = staticSuperBlock.blockSize - 1;
		}
		uint32_t cantBloques = 0;
		cantBloques += puntFin - puntInicio + 1;
		return cantBloques;
	}
}

int32_t cantBloquesNecesariosAux(uint64_t sizeViejo, uint64_t sizeNuevo) {
	div_t division = div(sizeViejo, staticSuperBlock.blockSize);
	uint32_t primerBloqueAOcupar = division.quot;
	if (division.rem != 0) {
		primerBloqueAOcupar++;
	}
	division = div(sizeNuevo, staticSuperBlock.blockSize);
	uint32_t ultimoBloqueAOcupar = division.quot;
	if (division.rem == 0 && division.quot > 0) {
		ultimoBloqueAOcupar--;
	}
	printfCUCA("Tengo que contar cuantos bloques necesito para ocupar desde el bloque numero [%d] hasta el bloque [%d].\n", primerBloqueAOcupar, ultimoBloqueAOcupar);
//SE VE SI SE TIENE QUE AGREGAR ALGUN PUNTERO DIRECTO
	uint64_t puntInicio = primerBloqueAOcupar;
	uint64_t puntFin = ultimoBloqueAOcupar;
	uint8_t error = 0;
	if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosDirectos(puntFin)) {
		//SOLO PUNTEROS DIRECTOS
		return cantBloquesNecesariosNivelN(sizeViejo, sizeNuevo, 0); //TODO COMPROBAR QUE ESTE BIEN
	} else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
		//PUNTEROS DIRECTOS Y PUNTERO INDIRECTO SIMPLE
		int32_t cantBloques = 0;
		cantBloques += cantBloquesNecesariosNivelN(sizeViejo, (12 * staticSuperBlock.blockSize), 0);
		printfCUCA("por ahora tengo [%d] bloques.\n", cantBloques);
		cantBloques += cantBloquesNecesariosNivelN(0, sizeNuevo - (12 * staticSuperBlock.blockSize), 1);
		return cantBloques;
	} else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
		//PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
		int32_t cantBloques = 0;
		cantBloques += cantBloquesNecesariosNivelN(sizeViejo, (12 * staticSuperBlock.blockSize), 0);
		cantBloques += cantBloquesNecesariosNivelN(0, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, 1);
		cantBloques += cantBloquesNecesariosNivelN(0, sizeNuevo - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), 2);
		return cantBloques;
	} else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
		//PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
		int32_t cantBloques = 0;
		cantBloques += cantBloquesNecesariosNivelN(sizeViejo, (12 * staticSuperBlock.blockSize), 0);
		cantBloques += cantBloquesNecesariosNivelN(0, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, 1);
		cantBloques += cantBloquesNecesariosNivelN(0, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize, 2);
		cantBloques += cantBloquesNecesariosNivelN(0, sizeNuevo - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), 3);
		return cantBloques;
	} else if (estaEntrePunterosIndirectosTriples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
		//SOLO PUNTERO INDIRECTO TRIPLE
		return cantBloquesNecesariosNivelN(sizeViejo - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), sizeNuevo - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), 3);
	} else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
		//PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
		int32_t cantBloques = 0;
		cantBloques += cantBloquesNecesariosNivelN(sizeViejo - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), maxCantBloquesNivelN(2) * staticSuperBlock.blockSize, 2);
		cantBloques += cantBloquesNecesariosNivelN(0, sizeNuevo - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), 3);
		return cantBloques;
	} else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
		//PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
		int32_t cantBloques = 0;
		cantBloques += cantBloquesNecesariosNivelN(sizeViejo - (12 * staticSuperBlock.blockSize), maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, 1);
		cantBloques += cantBloquesNecesariosNivelN(0, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize, 2);
		cantBloques += cantBloquesNecesariosNivelN(0, sizeNuevo - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), 3);
		return cantBloques;
	} else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
		//PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
		int32_t cantBloques = 0;
		cantBloques += cantBloquesNecesariosNivelN(sizeViejo - (12 * staticSuperBlock.blockSize), maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, 1);
		cantBloques += cantBloquesNecesariosNivelN(0, sizeNuevo - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), 2);
		return cantBloques;
	} else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
		//SOLO PUNTERO INDIRECTO SIMPLE
		printfCUCA("Cuento cuantos bloques necesito desde el [%d] hasta el [%d].\n", (uint32_t) puntInicio - 12, (uint32_t) puntFin - 12);
		return cantBloquesNecesariosNivelN(sizeViejo - (12 * staticSuperBlock.blockSize), sizeNuevo - (12 * staticSuperBlock.blockSize), 1);
	} else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
		//SOLO PUNTERO INDIRECTO DOBLE
		return cantBloquesNecesariosNivelN(sizeViejo - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), sizeNuevo - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), 2);
	}
	return error;
}

uint8_t agregarOLiberarBloquesNivelN(uint8_t numBlockGroup, uint32_t* punteros, uint64_t byteInicio, uint64_t byteFin, nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin, uint8_t esOcupar, uint8_t nivel) {
	if (nivel > 0) {
		//div_t divInicio = div(byteInicio, maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		struct {
			uint32_t quot;
			uint32_t rem;
		} divInicio;
		divInicio.quot = byteInicio / (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		divInicio.rem = byteInicio % (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		uint64_t puntInicio = divInicio.quot;
		uint64_t offInicio = divInicio.rem;
		/*if (divisionInicio.rem != 0) {
		 punteroIndInicio++;
		 }*/
		//div_t divFin = div(byteFin, maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		struct {
			uint32_t quot;
			uint32_t rem;
		} divFin;
		divFin.quot = byteFin / (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		divFin.rem = byteFin % (maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize);
		uint64_t puntFin = divFin.quot;
		uint64_t offFin = divFin.rem;
		if (offFin == 0 && puntFin > 0) {
			puntFin--;
			offFin = maxCantBloquesNivelN(nivel) * staticSuperBlock.blockSize - 1;
		}
		if (puntInicio == puntFin) {
			//EL PRIMERO ES EL ULTIMO
			printfCUCA("----Solo hay un puntero indirecto simple que tratar.\n");
			//uint64_t punteroDirInicio = divisionInicio.rem;
			//uint64_t punteroDirFin = punteroOffsetFin;
			uint8_t error = 0;
			if (esOcupar && offInicio == 0) {
				printfCUCA("------Es necesario ocupar un bloque para los direccionamientos indirectos simples.\n");
				error = agregarOLiberarBloquesNivelN(numBlockGroup, punteros + puntInicio, 0, 0, colaBloquesFte, colaBloquesFin, 1, 0);
			}
			if (!error) {
				uint32_t bloqueATratar = punteros[puntInicio];
				printfCUCA("--------Leo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
				uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
				if (esOcupar) {
					printfCUCA("----------Es necesario ocupar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) offInicio, (uint32_t) offFin);
					error = agregarOLiberarBloquesNivelN(numBlockGroup, bloquePunterosDirectos, offInicio, offFin, colaBloquesFte, colaBloquesFin, esOcupar, nivel - 1);
				} else {
					printfCUCA("----------Es necesario liberar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) offInicio, (uint32_t) offFin);
					error = agregarOLiberarBloquesNivelN(numBlockGroup, bloquePunterosDirectos, offInicio, offFin, colaBloquesFte, colaBloquesFin, esOcupar, nivel - 1);
					if (!error && offInicio == 0) {
						printfCUCA("------------Es necesario liberar el bloque [%d] correspondiente a los direccionamientos indirectos simples.\n", punteros[puntInicio]);
						error = agregarOLiberarBloquesNivelN(numBlockGroup, punteros + puntInicio, 0, 0, colaBloquesFte, colaBloquesFin, 0, 0);
					}
				}
				if (!error) {
					printfCUCA("--------------Escribo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
					escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
				}
				free(bloquePunterosDirectos);
			}
			return error;
		} else {
			printfCUCA("----Hay mas de un puntero indirecto simple que tratar.\n");
			uint64_t i;
			uint8_t error = 0;
			for (i = puntInicio; !error && i <= puntFin; i++) {
				printfCUCA("------Se trata el puntero indirecto simple numero [%d].\n", (uint32_t) i);
				uint64_t puntAuxInicio;
				uint64_t puntAuxFin;
				uint32_t bloqueATratar;
				if (i == puntInicio) {
					printfCUCA("--------Es el primer puntero indirecto simple en ser tratado.\n");
					puntAuxInicio = divInicio.rem;
					puntAuxFin = maxCantBloquesNivelN(1) - 1; //TODO SI ESTO FUNCIONA PUEDE SER QUE ESTE MAL EN OTROS LADOS
				} else if (i == puntFin) {
					printfCUCA("--------Es el ultimo puntero indirecto simple en ser tratado.\n");
					puntAuxInicio = 0;
					puntAuxFin = offFin;
				} else {
					printfCUCA("--------Es uno de los punteros indirectos simples intermedios en ser tratado.\n");
					puntAuxInicio = 0;
					puntAuxFin = maxCantBloquesNivelN(1) - 1; //TODO SI ESTO FUNCIONA PUEDE SER QUE ESTE MAL EN OTROS LADOS
				}
				if (esOcupar && puntAuxInicio == 0) {
					printfCUCA("----------Es necesario ocupar un bloque para los direccionamientos indirectos simples.\n");
					error = agregarOLiberarBloquesNivelN(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin, 1, 0);
				}
				if (!error) {
					bloqueATratar = punteros[i];
					printfCUCA("------------Leo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
					uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
					if (esOcupar) {
						printfCUCA("--------------Es necesario ocupar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) puntAuxInicio, (uint32_t) puntAuxFin);
						error = agregarOLiberarBloquesNivelN(numBlockGroup, bloquePunterosDirectos, puntAuxInicio, puntAuxFin, colaBloquesFte, colaBloquesFin, esOcupar, nivel - 1);
					} else {
						printfCUCA("--------------Es necesario liberar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) puntAuxInicio, (uint32_t) puntAuxFin);
						error = agregarOLiberarBloquesNivelN(numBlockGroup, bloquePunterosDirectos, puntAuxInicio, puntAuxFin, colaBloquesFte, colaBloquesFin, esOcupar, nivel - 1);
						if (!error && puntAuxInicio == 0) {
							printfCUCA("------------Es necesario liberar el bloque [%d] correspondiente a los direccionamientos indirectos simples.\n", punteros[i]);
							error = agregarOLiberarBloquesNivelN(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin, 0, 0);
						}
					}
					if (!error) {
						printfCUCA("--------------Escribo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
						escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
					}
					free(bloquePunterosDirectos);
				}
			}
			return error;
		}
	} else {
		div_t divInicio = div(byteInicio, staticSuperBlock.blockSize);
		uint64_t puntInicio = divInicio.quot;
		if (divInicio.rem != 0) {
			puntInicio++;
		}
		div_t divFin = div(byteFin, staticSuperBlock.blockSize);
		uint64_t puntFin = divFin.quot;
		uint64_t offFin = divFin.rem;
		if (offFin == 0 && puntFin > 0) {
			puntFin--;
			offFin = staticSuperBlock.blockSize - 1;
		}
		if (esOcupar) {
			printfCUCA("Tengo que agregar [%d] Bloques de Datos.\n", (uint32_t) (puntFin - puntInicio + 1));
			uint64_t i;
			for (i = puntInicio; i <= puntFin; i++) {
				printfCUCA("--Necesito un bloque para el direccionamiento numero [%d].\n", (uint32_t) i);
				uint32_t numBloqueGlobal = desencolarNumBloque(colaBloquesFte, colaBloquesFin); //buscarYOcuparBloqueLibre(numBlockGroup);
				printfCUCA("----Obtuve el bloque con direccion local [%d] de la cola de bloques.\n", (uint32_t) numBloqueGlobal);
				if (numBloqueGlobal > 0) {
					printfCUCA("------La direccion global del bloque es [%d].\n", numBloqueGlobal);
					punteros[i] = (uint32_t) numBloqueGlobal;
					char* info = (char*) malloc(staticSuperBlock.blockSize);
					memset(info, '\0', staticSuperBlock.blockSize);
					escribirBloqueGlobal(numBloqueGlobal, info);
					free(info);
				} else {
					return 1;
				}
			}
			return 0;
		} else {
			printfCUCA("Tengo que liberar %d bloques direccionados directamente.\n", (uint32_t) (puntFin - puntInicio + 1));
			uint64_t i;
			for (i = puntInicio; i <= puntFin; i++) {
				printfCUCA("--Tengo que liberar el bloque con direccionamiento numero [%d].\n", (uint32_t) i);
				uint32_t numBloqueGlobal = punteros[i];
				printfCUCA("----La direccion global del bloque es la [%d].\n", numBloqueGlobal);
				//uint32_t numBloqueLocal = deBloqueGlobalALocal(numBlockGroup, numBloqueGlobal);
				//printfCUCA("------Agrego el bloque con direccion local [%d] para ser liberado posteriormente.\n", numBloqueLocal);
				encolarNumBloque(colaBloquesFte, colaBloquesFin, numBloqueGlobal); //liberarBloqueOcupado(numBlockGroup, numBloqueLocal);
				punteros[i] = 0;
			}
			return 0;
		}
	}
}

uint8_t agregarOLiberarBloquesAInodoAux(uint8_t numBlockGroup, inodeStructure_t* inodo, uint64_t sizeNuevo, uint8_t esOcupar) {
	uint64_t sizeMenor;
	uint64_t sizeMayor;
	if ((*inodo).size > sizeNuevo) {
		sizeMenor = sizeNuevo;
		sizeMayor = (*inodo).size;
	} else {
		sizeMenor = (*inodo).size;
		sizeMayor = sizeNuevo;
	}
	uint32_t cantBloques = 0;
	if (esOcupar) {
		cantBloques = (uint32_t) cantBloquesNecesariosAux(sizeMenor, sizeMayor);
		printfCUCA("En total voy a necesitar [%d] bloques.\n", cantBloques);
	}
	uint8_t error = 0;
	nodoNumBloque_t* colaBloquesFte = NULL;
	nodoNumBloque_t* colaBloquesFin = NULL;
	if (esOcupar) {
		error = buscarYOcuparNBloquesLibresGlobales(&colaBloquesFte, &colaBloquesFin, cantBloques);
		printfCUCA("Ocupe los bloques:\n");
		nodoNumBloque_t* aux = colaBloquesFte;
		while (aux != NULL) {
			printfCUCA("-----[%d].\n", aux->numBloque);
			aux = aux->sig;
		}
	}
	if (!error) {
		div_t division = div(sizeMenor, staticSuperBlock.blockSize);
		uint32_t primerBloqueAOcupar = division.quot;
		if (division.rem != 0) {
			primerBloqueAOcupar++;
		}
		printfCUCA("primerBloqueAOcupar: %d\n", primerBloqueAOcupar);
		division = div(sizeMayor, staticSuperBlock.blockSize);
		uint32_t ultimoBloqueAOcupar = division.quot;
		if (division.rem == 0 && division.quot > 0) {
			ultimoBloqueAOcupar--;
		}
		printfCUCA("Hay que agregar o quitar bloques desde el bloque numero [%d] hasta el bloque [%d].\n", primerBloqueAOcupar, ultimoBloqueAOcupar);
		//SE VE SI SE TIENE QUE AGREGAR ALGUN PUNTERO DIRECTO
		uint64_t puntInicio = primerBloqueAOcupar;
		uint64_t puntFin = ultimoBloqueAOcupar;
		if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosDirectos(puntFin)) {
			//SOLO PUNTEROS DIRECTOS
			printfCUCA("Solo se trataran los punteros directos.\n");
			if (esOcupar) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, sizeMayor, &colaBloquesFte, &colaBloquesFin, 1, 0);
			} else {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, sizeMayor, &colaBloquesFte, &colaBloquesFin, 0, 0);
			}
		} else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
			//PUNTEROS DIRECTOS Y PUNTERO INDIRECTO SIMPLE
			printfCUCA("Se trataran los punteros directos y el indirecto simple.\n");
			if (esOcupar) { //TODO revisar 12 * staticSuperBlock.blockSize
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, 12 * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, 1, 0);
			} else {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, 12 * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, 0, 0);
			}
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 12, 0, sizeMayor - (12 * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 1);
			}
		} else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
			//PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
			printfCUCA("Se trataran los punteros directos, el indirecto simple y el indirecto doble.\n");
			if (esOcupar) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, 12 * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, 1, 0);
			} else {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, 12 * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, 0, 0);
			}
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 12, 0, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 1);
				if (!error) {
					error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 13, 0, sizeMayor - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 2);
				}
			}
		} else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
			//PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
			if (esOcupar) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, 12 * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, 1, 0);
			} else {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block, sizeMenor, 11 * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, 0, 0);
			}
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 12, 0, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 1);
				if (!error) {
					error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 13, 0, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 2);
					if (!error) {
						error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 14, 0, sizeMayor - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 3);
					}
				}
			}
		} else if (estaEntrePunterosIndirectosTriples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
			//SOLO PUNTERO INDIRECTO TRIPLE
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 14, sizeMenor - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), sizeMayor - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 3);
			}
		} else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
			//PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
			error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 13, sizeMenor - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), maxCantBloquesNivelN(2) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 2);
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 14, 0, sizeMayor - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 3);
			}
		} else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
			//PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
			error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 12, sizeMenor - (12 * staticSuperBlock.blockSize), maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 1);
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 13, 0, maxCantBloquesNivelN(2) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 2);
				if (!error) {
					error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 14, 0, sizeMayor - ((12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 3);
				}
			}
		} else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
			//PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
			error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 12, sizeMenor - (12 * staticSuperBlock.blockSize), maxCantBloquesNivelN(1) * staticSuperBlock.blockSize, &colaBloquesFte, &colaBloquesFin, esOcupar, 1);
			if (!error) {
				error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 13, 0, sizeMayor - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 2);
			}
		} else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
			//SOLO PUNTERO INDIRECTO SIMPLE
			error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 12, sizeMenor - (12 * staticSuperBlock.blockSize), sizeMayor - (12 * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 1);
		} else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
			//SOLO PUNTERO INDIRECTO DOBLE
			error = agregarOLiberarBloquesNivelN(numBlockGroup, (*inodo).block + 13, sizeMenor - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), sizeMayor - ((12 + maxCantBloquesNivelN(1)) * staticSuperBlock.blockSize), &colaBloquesFte, &colaBloquesFin, esOcupar, 2);
		}
		if (!error && !esOcupar) {
			printfCUCA("Tengo que liberar los siguientes bloques:\n");
			nodoNumBloque_t* aux = colaBloquesFte;
			while (aux != NULL) {
				printfCUCA("-----[%d].\n", aux->numBloque);
				aux = aux->sig;
			}
			error = liberarNBloquesOcupadosGlobales(&colaBloquesFte, &colaBloquesFin);
		}
	}
	return error;
}

/*int32_t cantBloquesNecesariosNivel1(uint64_t bloqueInicio, uint64_t bloqueFin) {
 printfCUCA("El bloque de inicio es el [%d], y el de fin es el [%d].\n", (uint32_t) bloqueInicio, (uint32_t) bloqueFin);
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(1) * staticSuperBlock.blockSize);
 uint64_t punteroIndInicio = divisionInicio.quot;
 //if (divisionInicio.rem != 0) {
 //printfCUCA("Incremento el puntero de Inicio.\n");
 //punteroIndInicio++;
 //}
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(1));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0 && divisionFin.quot > 0) {
 printfCUCA("Le saco un puntero y le corro el offset.\n");
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(1) - 1;
 }
 printfCUCA("El puntero indirecto de inicio es el [%d] y el de fin es el [%d].\n", (uint32_t) punteroIndInicio, (uint32_t) punteroIndFin);
 if (punteroIndInicio == punteroIndFin) {
 printfCUCA("Hay un solo puntero indirecto.\n");
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 int32_t cantBloques = 0;
 if (punteroDirInicio == 0) {
 printfCUCA("Tengo que contar el bloque de direccionamientos directos.\n");
 cantBloques++;
 }
 printfCUCA("El puntero de inicio es el [%d] y el de fin es el [%d].\n", (uint32_t) punteroDirInicio, (uint32_t) punteroDirFin);
 cantBloques += punteroDirFin - punteroDirInicio + 1; //TODO COMPROBAR QUE ESTE BIEN
 return cantBloques;
 } else {
 uint64_t i;
 uint32_t cantBloques = 0;
 for (i = punteroIndInicio; i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(1) - 1;
 } else if (i == punteroIndFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(1) - 1;
 }
 if (punteroDirInicio == 0) {
 cantBloques++;
 }
 cantBloques += punteroDirFin - punteroDirInicio + 1; //TODO COMPROBAR QUE ESTE BIEN
 }
 return cantBloques;
 }
 }*/

/*int32_t cantBloquesNecesariosNivel2(uint64_t bloqueInicio, uint64_t bloqueFin) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(2));
 uint64_t punteroIndInicio = divisionInicio.quot;
 //if (divisionInicio.rem != 0) {
 //punteroIndInicio++;
 //}
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(2));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0 && divisionFin.quot > 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(2) - 1;
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 int32_t cantBloques = 0;
 if (punteroDirInicio == 0) {
 cantBloques++;
 }
 cantBloques += cantBloquesNecesariosNivel1(punteroDirInicio, punteroDirFin);
 return cantBloques;
 } else {
 uint64_t i;
 int32_t cantBloques = 0;
 for (i = punteroIndInicio; i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(2) - 1;
 } else if (i == punteroIndFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(2) - 1;
 }
 if (punteroDirInicio == 0) {
 cantBloques++;
 }
 cantBloques += cantBloquesNecesariosNivel1(punteroDirInicio, punteroDirFin);
 }
 return cantBloques;
 }
 }*/

/*int32_t cantBloquesNecesariosNivel3(uint64_t bloqueInicio, uint64_t bloqueFin) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(3));
 uint64_t punteroIndInicio = divisionInicio.quot;
 //if (divisionInicio.rem != 0) {
 //punteroIndInicio++;
 //}
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(3));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0 && divisionFin.quot > 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(3) - 1;
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 int32_t cantBloques = 0;
 if (punteroDirInicio == 0) {
 cantBloques++;
 }
 cantBloques += cantBloquesNecesariosNivel2(punteroDirInicio, punteroDirFin);
 return cantBloques;
 } else {
 uint64_t i;
 int32_t cantBloques = 0;
 for (i = punteroIndInicio; i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(3) - 1;
 } else if (i == punteroIndFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(3) - 1;
 }
 if (punteroDirInicio == 0) {
 cantBloques++;
 }
 cantBloques += cantBloquesNecesariosNivel2(punteroDirInicio, punteroDirFin);
 }
 return cantBloques;
 }
 }*/

/*int32_t cantBloquesNecesarios(uint64_t sizeViejo, uint64_t sizeNuevo) {
 div_t division = div(sizeViejo, staticSuperBlock.blockSize);
 uint32_t primerBloqueAOcupar = division.quot;
 if (division.rem != 0) {
 primerBloqueAOcupar++;
 }
 division = div(sizeNuevo, staticSuperBlock.blockSize);
 uint32_t ultimoBloqueAOcupar = division.quot;
 if (division.rem == 0 && division.quot > 0) {
 ultimoBloqueAOcupar--;
 }
 printfCUCA("Tengo que contar cuantos bloques necesito para ocupar desde el bloque numero [%d] hasta el bloque [%d].\n", primerBloqueAOcupar, ultimoBloqueAOcupar);
 //SE VE SI SE TIENE QUE AGREGAR ALGUN PUNTERO DIRECTO
 uint64_t puntInicio = primerBloqueAOcupar;
 uint64_t puntFin = ultimoBloqueAOcupar;
 uint8_t error = 0;
 if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosDirectos(puntFin)) {
 //SOLO PUNTEROS DIRECTOS
 return (puntFin - puntInicio + 1); //TODO COMPROBAR QUE ESTE BIEN
 } else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
 //PUNTEROS DIRECTOS Y PUNTERO INDIRECTO SIMPLE
 int32_t cantBloques = 0;
 cantBloques += 11 - puntInicio + 1;
 printfCUCA("por ahora tengo [%d] bloques.\n", cantBloques);
 cantBloques += cantBloquesNecesariosNivel1(0, puntFin - 12);
 return cantBloques;
 } else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
 //PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
 int32_t cantBloques = 0;
 cantBloques += 11 - puntInicio + 1;
 cantBloques += cantBloquesNecesariosNivel1(0, maxCantBloquesNivelN(1));
 cantBloques += cantBloquesNecesariosNivel2(0, puntFin - 12 - maxCantBloquesNivelN(1));
 return cantBloques;
 } else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
 int32_t cantBloques = 0;
 cantBloques += 11 - puntInicio + 1;
 cantBloques += cantBloquesNecesariosNivel1(0, maxCantBloquesNivelN(1));
 cantBloques += cantBloquesNecesariosNivel2(0, maxCantBloquesNivelN(2));
 cantBloques += cantBloquesNecesariosNivel3(0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 return cantBloques;
 } else if (estaEntrePunterosIndirectosTriples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //SOLO PUNTERO INDIRECTO TRIPLE
 return cantBloquesNecesariosNivel3(puntInicio - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 } else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
 int32_t cantBloques = 0;
 cantBloques += cantBloquesNecesariosNivel2(puntInicio - 12 - maxCantBloquesNivelN(1), maxCantBloquesNivelN(2));
 cantBloques += cantBloquesNecesariosNivel3(0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 return cantBloques;
 } else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
 int32_t cantBloques = 0;
 cantBloques += cantBloquesNecesariosNivel1(puntInicio - 12, maxCantBloquesNivelN(1));
 cantBloques += cantBloquesNecesariosNivel2(0, maxCantBloquesNivelN(2));
 cantBloques += cantBloquesNecesariosNivel3(0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 return cantBloques;
 } else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
 //PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
 int32_t cantBloques = 0;
 cantBloques += cantBloquesNecesariosNivel1(puntInicio - 12, maxCantBloquesNivelN(1));
 cantBloques += cantBloquesNecesariosNivel2(0, puntFin - 12 - maxCantBloquesNivelN(1));
 return cantBloques;
 } else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
 //SOLO PUNTERO INDIRECTO SIMPLE
 printfCUCA("Cuento cuantos bloques necesito desde el [%d] hasta el [%d].\n", (uint32_t) puntInicio - 12, (uint32_t) puntFin - 12);
 return cantBloquesNecesariosNivel1(puntInicio - 12, puntFin - 12);
 } else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
 //SOLO PUNTERO INDIRECTO DOBLE
 return cantBloquesNecesariosNivel2(puntInicio - 12 - maxCantBloquesNivelN(1), puntFin - 12 - maxCantBloquesNivelN(1));
 }
 return error;
 }*/

/*uint8_t hayNBloquesLibresEnGrupo(uint8_t numBlockGroup, uint32_t cantBloquesNecesarios) {
 groupDescriptor_t* groupDescriptorTable = leerGroupDescriptorTable();
 uint8_t hayLugar;
 if (groupDescriptorTable[numBlockGroup].freeBlocksCount >= cantBloquesNecesarios) {
 printfCUCA("Tengo [%d] bloques libres y necesito [%d]. Puedo continuar.\n", groupDescriptorTable[numBlockGroup].freeBlocksCount, cantBloquesNecesarios);
 hayLugar = 1;
 } else {
 printfCUCA("Tengo [%d] bloques libres y necesito [%d]. No puedo continuar.\n", groupDescriptorTable[numBlockGroup].freeBlocksCount, cantBloquesNecesarios);
 hayLugar = 0;
 }
 free(groupDescriptorTable);
 return hayLugar;
 }*/

/*uint8_t agregarBloquesNivel0(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin, nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin) {
 printfCUCA("Tengo que agregar [%d] Bloques de Datos.\n", (uint32_t)(bloqueFin - bloqueInicio + 1));
 uint64_t i;
 for (i = bloqueInicio; i <= bloqueFin; i++) {
 printfCUCA("--Necesito un bloque para el direccionamiento numero [%d].\n", (uint32_t) i);
 int64_t numBloqueLocal = desencolarNumBloque(colaBloquesFte, colaBloquesFin); //buscarYOcuparBloqueLibre(numBlockGroup);
 printfCUCA("----Obtuve el bloque con direccion local [%d] de la cola de bloques.\n", (uint32_t) numBloqueLocal);
 if (numBloqueLocal > 0) {
 uint32_t numBloqueGlobal = (uint32_t) deBloqueLocalAGlobal(numBlockGroup, numBloqueLocal);
 printfCUCA("------La direccion global del bloque es [%d].\n", numBloqueGlobal);
 punteros[i] = (uint32_t) numBloqueGlobal;
 char* info = (char*) malloc(staticSuperBlock.blockSize);
 memset(info, '\0', staticSuperBlock.blockSize);
 escribirBloqueGlobal(numBloqueGlobal, info);
 free(info);
 } else {
 return 1;
 }
 }
 return 0;
 }*/

/*uint8_t liberarBloquesNivel0(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin, nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin) {
 printfCUCA("Tengo que liberar %d bloques direccionados directamente.\n", (uint32_t)(bloqueFin - bloqueInicio + 1));
 uint64_t i;
 for (i = bloqueInicio; i <= bloqueFin; i++) {
 printfCUCA("--Tengo que liberar el bloque con direccionamiento numero [%d].\n", (uint32_t) i);
 uint32_t numBloqueGlobal = punteros[i];
 printfCUCA("----La direccion global del bloque es la [%d].\n", numBloqueGlobal);
 uint32_t numBloqueLocal = deBloqueGlobalALocal(numBlockGroup, numBloqueGlobal);
 printfCUCA("------Agrego el bloque con direccion local [%d] para ser liberado posteriormente.\n", numBloqueLocal);
 encolarNumBloque(colaBloquesFte, colaBloquesFin, numBloqueLocal); //liberarBloqueOcupado(numBlockGroup, numBloqueLocal);
 punteros[i] = 0;
 }
 return 0;
 }*/

/*uint8_t agregarOLiberarBloquesNivel1(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin, nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin, uint8_t esOcupar) {
 printfCUCA("Inicio la ocupacion o liberacion de bloques correspondientes a un indireccionamiento simple.\n");
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(1));
 uint64_t punteroIndInicio = divisionInicio.quot;
 //if (divisionInicio.rem != 0) {
 //punteroIndInicio++;
 //}
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(1));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0 && divisionFin.quot > 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(1) - 1; //TODO SI ESTO FUNCIONA PUEDE SER QUE ESTE MAL EN OTROS LADOS
 }
 printfCUCA("--Hay [%d] punteros Indirectos Simples que ocupar o liberar.\n", (uint32_t)(punteroIndFin - punteroIndInicio + 1));
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 printfCUCA("----Solo hay un puntero indirecto simple que tratar.\n");
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 uint8_t error = 0;
 if (esOcupar && punteroDirInicio == 0) {
 printfCUCA("------Es necesario ocupar un bloque para los direccionamientos indirectos simples.\n");
 error = agregarBloquesNivel0(numBlockGroup, punteros + punteroIndInicio, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 uint32_t bloqueATratar = punteros[punteroIndInicio];
 printfCUCA("--------Leo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
 if (esOcupar) {
 printfCUCA("----------Es necesario ocupar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) punteroDirInicio, (uint32_t) punteroDirFin);
 error = agregarBloquesNivel0(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin);
 } else {
 printfCUCA("----------Es necesario liberar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) punteroDirInicio, (uint32_t) punteroDirFin);
 error = liberarBloquesNivel0(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin);
 if (!error && punteroDirInicio == 0) {
 printfCUCA("------------Es necesario liberar el bloque [%d] correspondiente a los direccionamientos indirectos simples.\n", punteros[punteroIndInicio]);
 error = liberarBloquesNivel0(numBlockGroup, punteros + punteroIndInicio, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 }
 if (!error) {
 printfCUCA("--------------Escribo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
 escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
 }
 free(bloquePunterosDirectos);
 }
 return error;
 } else {
 printfCUCA("----Hay mas de un puntero indirecto simple que tratar.\n");
 uint64_t i;
 uint8_t error = 0;
 for (i = punteroIndInicio; !error && i <= punteroIndFin; i++) {
 printfCUCA("------Se trata el puntero indirecto simple numero [%d].\n", (uint32_t) i);
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 uint32_t bloqueATratar;
 if (i == punteroIndInicio) {
 printfCUCA("--------Es el primer puntero indirecto simple en ser tratado.\n");
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(1) - 1; //TODO SI ESTO FUNCIONA PUEDE SER QUE ESTE MAL EN OTROS LADOS
 } else if (i == punteroIndFin) {
 printfCUCA("--------Es el ultimo puntero indirecto simple en ser tratado.\n");
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 printfCUCA("--------Es uno de los punteros indirectos simples intermedios en ser tratado.\n");
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(1) - 1; //TODO SI ESTO FUNCIONA PUEDE SER QUE ESTE MAL EN OTROS LADOS
 }
 if (esOcupar && punteroDirInicio == 0) {
 printfCUCA("----------Es necesario ocupar un bloque para los direccionamientos indirectos simples.\n");
 error = agregarBloquesNivel0(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 bloqueATratar = punteros[i];
 printfCUCA("------------Leo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
 if (esOcupar) {
 printfCUCA("--------------Es necesario ocupar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) punteroDirInicio, (uint32_t) punteroDirFin);
 error = agregarBloquesNivel0(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin);
 } else {
 printfCUCA("--------------Es necesario liberar desde el puntero directo numero [%d] hasta el puntero numero [%d].\n", (uint32_t) punteroDirInicio, (uint32_t) punteroDirFin);
 error = liberarBloquesNivel0(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin);
 if (!error && punteroDirInicio == 0) {
 printfCUCA("------------Es necesario liberar el bloque [%d] correspondiente a los direccionamientos indirectos simples.\n", punteros[i]);
 error = liberarBloquesNivel0(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 }
 if (!error) {
 printfCUCA("--------------Escribo el bloque [%d] correspondiente al bloque con direccionamientos directos.\n", bloqueATratar);
 escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
 }
 free(bloquePunterosDirectos);
 }
 }
 return error;
 }
 }*/

/*uint8_t agregarOLiberarBloquesNivel2(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin, nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin, uint8_t esOcupar) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(2));
 uint64_t punteroIndInicio = divisionInicio.quot;
 //if (divisionInicio.rem != 0) {
 //punteroIndInicio++;
 //}
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(2));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0 && divisionFin.quot > 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(2) - 1;
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 uint8_t error = 0;
 if (esOcupar && punteroDirInicio == 0) {
 error = agregarBloquesNivel0(numBlockGroup, punteros + punteroIndInicio, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 uint32_t bloqueATratar = punteros[punteroIndInicio];
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
 error = agregarOLiberarBloquesNivel1(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin, esOcupar);
 if (!esOcupar && !error && punteroDirInicio == 0) {
 error = liberarBloquesNivel0(numBlockGroup, punteros + punteroIndInicio, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
 }
 free(bloquePunterosDirectos);
 }
 return error;
 } else {
 uint64_t i;
 uint8_t error = 0;
 for (i = punteroIndInicio; !error && i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 uint32_t bloqueATratar;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(2) - 1;
 } else if (i == punteroIndFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(2) - 1;
 }
 if (esOcupar && punteroDirInicio == 0) {
 error = agregarBloquesNivel0(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 bloqueATratar = punteros[i];
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
 error = agregarOLiberarBloquesNivel1(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin, esOcupar);
 if (!esOcupar && !error && punteroDirInicio == 0) {
 error = liberarBloquesNivel0(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
 }
 free(bloquePunterosDirectos);
 }
 return error;
 }
 }*/

/*uint8_t agregarOLiberarBloquesNivel3(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin, nodoNumBloque_t** colaBloquesFte, nodoNumBloque_t** colaBloquesFin, uint8_t esOcupar) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(3));
 uint64_t punteroIndInicio = divisionInicio.quot;
 //if (divisionInicio.rem != 0) {
 //punteroIndInicio++;
 //}
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(3));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0 && divisionFin.quot > 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(3) - 1;
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 uint8_t error = 0;
 if (esOcupar && punteroDirInicio == 0) {
 error = agregarBloquesNivel0(numBlockGroup, punteros + punteroIndInicio, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 uint32_t bloqueATratar = punteros[punteroIndInicio];
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
 error = agregarOLiberarBloquesNivel2(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin, esOcupar);
 if (!esOcupar && !error && punteroDirInicio == 0) {
 error = liberarBloquesNivel0(numBlockGroup, punteros + punteroIndInicio, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
 }
 free(bloquePunterosDirectos);
 }
 return error;
 } else {
 uint64_t i;
 uint8_t error = 0;
 for (i = punteroIndInicio; !error && i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 uint32_t bloqueATratar;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(3) - 1;
 } else if (i == punteroIndFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(3) - 1;
 }
 if (esOcupar && punteroDirInicio == 0) {
 error = agregarBloquesNivel0(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 bloqueATratar = punteros[i];
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(bloqueATratar);
 error = agregarOLiberarBloquesNivel2(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin, colaBloquesFte, colaBloquesFin, esOcupar);
 if (!esOcupar && !error && punteroDirInicio == 0) {
 error = liberarBloquesNivel0(numBlockGroup, punteros + i, 0, 0, colaBloquesFte, colaBloquesFin);
 }
 if (!error) {
 escribirBloqueGlobal(bloqueATratar, (char*) bloquePunterosDirectos);
 }
 free(bloquePunterosDirectos);
 }
 return error;
 }
 }*/

/*uint8_t agregarOLiberarBloquesAInodo(uint8_t numBlockGroup, inodeStructure_t* inodo, uint64_t sizeNuevo, uint8_t esOcupar) {
 uint64_t sizeMenor;
 uint64_t sizeMayor;
 if ((*inodo).size > sizeNuevo) {
 sizeMenor = sizeNuevo;
 sizeMayor = (*inodo).size;
 } else {
 sizeMenor = (*inodo).size;
 sizeMayor = sizeNuevo;
 }
 uint32_t cantBloques = 0;
 if (esOcupar) {
 cantBloques = (uint32_t) cantBloquesNecesarios(sizeMenor, sizeMayor);
 printfCUCA("En total voy a necesitar [%d][%d] bloques.\n", cantBloques, cantBloquesNecesariosAux(sizeMenor, sizeMayor));
 }
 //if ((esOcupar && hayNBloquesLibresEnGrupo(numBlockGroup, cantBloques)) || !esOcupar) {
 uint8_t error = 0;
 nodoNumBloque_t* colaBloquesFte = NULL;
 nodoNumBloque_t* colaBloquesFin = NULL;
 if (esOcupar) {
 error = buscarYOcuparNBloquesLibresGlobales(&colaBloquesFte, &colaBloquesFin, cantBloques);
 printfCUCA("Ocupe los bloques:\n");
 nodoNumBloque_t* aux = colaBloquesFte;
 while (aux != NULL) {
 printfCUCA("-----[%d].\n", aux->numBloque);
 aux = aux->sig;
 }
 }
 if (!error) {
 div_t division = div(sizeMenor, staticSuperBlock.blockSize);
 uint32_t primerBloqueAOcupar = division.quot;
 if (division.rem != 0) {
 primerBloqueAOcupar++;
 }
 division = div(sizeMayor, staticSuperBlock.blockSize);
 uint32_t ultimoBloqueAOcupar = division.quot;
 if (division.rem == 0 && division.quot > 0) {
 ultimoBloqueAOcupar--;
 }
 printfCUCA("Hay que agregar o quitar bloques desde el bloque numero [%d] hasta el bloque [%d].\n", primerBloqueAOcupar, ultimoBloqueAOcupar);
 //SE VE SI SE TIENE QUE AGREGAR ALGUN PUNTERO DIRECTO
 uint64_t puntInicio = primerBloqueAOcupar;
 uint64_t puntFin = ultimoBloqueAOcupar;
 if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosDirectos(puntFin)) {
 //SOLO PUNTEROS DIRECTOS
 printfCUCA("Solo se trataran los punteros directos.\n");
 if (esOcupar) {
 error = agregarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, puntFin, &colaBloquesFte, &colaBloquesFin);
 } else {
 error = liberarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, puntFin, &colaBloquesFte, &colaBloquesFin);
 }
 } else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
 //PUNTEROS DIRECTOS Y PUNTERO INDIRECTO SIMPLE
 printfCUCA("Se trataran los punteros directos y el indirecto simple.\n");
 if (esOcupar) {
 error = agregarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, 11, &colaBloquesFte, &colaBloquesFin);
 } else {
 error = liberarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, 11, &colaBloquesFte, &colaBloquesFin);
 }
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 //if (!error) {
 error = agregarOLiberarBloquesNivel1(numBlockGroup, (*inodo).block + 12, 0, puntFin - 12, &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 //}
 }
 } else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
 //PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
 printfCUCA("Se trataran los punteros directos, el indirecto simple y el indirecto doble.\n");
 if (esOcupar) {
 error = agregarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, 11, &colaBloquesFte, &colaBloquesFin);
 } else {
 error = liberarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, 11, &colaBloquesFte, &colaBloquesFin);
 }
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel1(numBlockGroup, (*inodo).block + 12, 0, maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel2(numBlockGroup, (*inodo).block + 13, 0, puntFin - 12 - maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 }
 }
 } else if (estaEntrePunterosDirectos(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //PUNTEROS DIRECTOS, PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
 if (esOcupar) {
 error = agregarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, 11, &colaBloquesFte, &colaBloquesFin);
 } else {
 error = liberarBloquesNivel0(numBlockGroup, (*inodo).block, puntInicio, 11, &colaBloquesFte, &colaBloquesFin);
 }
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel1(numBlockGroup, (*inodo).block + 12, 0, maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel2(numBlockGroup, (*inodo).block + 13, 0, maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel3(numBlockGroup, (*inodo).block + 14, 0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 }
 }
 }
 } else if (estaEntrePunterosIndirectosTriples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //SOLO PUNTERO INDIRECTO TRIPLE
 if (!error) {
 //if (esOcupar && puntInicio == 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel3(numBlockGroup, (*inodo).block + 14, puntInicio - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar && puntInicio == 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 }
 } else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
 //if (esOcupar && puntInicio == 12 + maxCantBloquesNivelN(1)) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel2(numBlockGroup, (*inodo).block + 13, puntInicio - 12 - maxCantBloquesNivelN(1), maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar && puntInicio == 12 + maxCantBloquesNivelN(1)) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel3(numBlockGroup, (*inodo).block + 14, 0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 }
 } else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosTriples(puntFin)) {
 //PUNTERO INDIRECTO SIMPLE, PUNTERO INDIRECTO DOBLE Y PUNTERO INDIRECTO TRIPLE
 //if (esOcupar && puntInicio == 12) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel1(numBlockGroup, (*inodo).block + 12, puntInicio - 12, maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar && puntInicio == 12) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel2(numBlockGroup, (*inodo).block + 13, 0, maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel3(numBlockGroup, (*inodo).block + 14, 0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 14, 0, 0);
 //}
 }
 }
 } else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
 //PUNTERO INDIRECTO SIMPLE Y PUNTERO INDIRECTO DOBLE
 //if (esOcupar && puntInicio == 12) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel1(numBlockGroup, (*inodo).block + 12, puntInicio - 12, maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar && puntInicio == 12) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 if (!error) {
 //if (esOcupar) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel2(numBlockGroup, (*inodo).block + 13, 0, puntFin - 12 - maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 }
 } else if (estaEntrePunterosIndirectosSimples(puntInicio) && estaEntrePunterosIndirectosSimples(puntFin)) {
 //SOLO PUNTERO INDIRECTO SIMPLE
 //if (esOcupar && puntInicio == 12) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel1(numBlockGroup, (*inodo).block + 12, puntInicio - 12, puntFin - 12, &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar && puntInicio == 12) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 12, 0, 0);
 //}
 } else if (estaEntrePunterosIndirectosDobles(puntInicio) && estaEntrePunterosIndirectosDobles(puntFin)) {
 //SOLO PUNTERO INDIRECTO DOBLE
 //if (esOcupar && puntInicio == 12 + maxCantBloquesNivelN(1)) {
 //error = agregarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 error = agregarOLiberarBloquesNivel2(numBlockGroup, (*inodo).block + 13, puntInicio - 12 - maxCantBloquesNivelN(1), puntFin - 12 - maxCantBloquesNivelN(1), &colaBloquesFte, &colaBloquesFin, esOcupar);
 //if (!error && !esOcupar && puntInicio == 12 + maxCantBloquesNivelN(1)) {
 //error = liberarBloquesNivel0(numBlockGroup, (*inodo).block + 13, 0, 0);
 //}
 }
 if (!error && !esOcupar) {
 printfCUCA("Tengo que liberar los siguientes bloques:\n");
 nodoNumBloque_t* aux = colaBloquesFte;
 while (aux != NULL) {
 printfCUCA("-----[%d].\n", aux->numBloque);
 aux = aux->sig;
 }
 error = liberarNBloquesOcupados(&colaBloquesFte, &colaBloquesFin, numBlockGroup);
 }
 }
 return error;
 //} else {
 //NO HAY ESPACIO EN ESTE BLOQUE
 //return 1;
 //}
 }*/

/*uint8_t liberarBloquesNivel1(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(1));
 uint64_t punteroIndInicio = divisionInicio.quot;
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(1));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(1);
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(punteros[punteroIndInicio]);
 return liberarBloquesNivel0(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin);
 } else {
 uint64_t i;
 uint8_t error = 0;
 for (i = punteroIndInicio; !error && i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(1);
 } else if (i == punteroDirFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(1);
 }
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(punteros[i]);
 error = liberarBloquesNivel0(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin);
 }
 return error;
 }
 }

 uint8_t liberarBloquesNivel2(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(2));
 uint64_t punteroIndInicio = divisionInicio.quot;
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(2));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(2);
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(punteros[punteroIndInicio]);
 return liberarBloquesNivel1(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin);
 } else {
 uint64_t i;
 uint8_t error = 0;
 for (i = punteroIndInicio; !error && i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(2);
 } else if (i == punteroDirFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(2);
 }
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(punteros[i]);
 error = liberarBloquesNivel1(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin);
 }
 return error;
 }
 }

 uint8_t liberarBloquesNivel3(uint8_t numBlockGroup, uint32_t* punteros, uint64_t bloqueInicio, uint64_t bloqueFin) {
 div_t divisionInicio = div(bloqueInicio, maxCantBloquesNivelN(3));
 uint64_t punteroIndInicio = divisionInicio.quot;
 div_t divisionFin = div(bloqueFin, maxCantBloquesNivelN(3));
 uint64_t punteroIndFin = divisionFin.quot;
 uint64_t punteroOffsetFin = divisionFin.rem;
 if (divisionFin.rem == 0) {
 punteroIndFin--;
 punteroOffsetFin = maxCantBloquesNivelN(3);
 }
 if (punteroIndInicio == punteroIndFin) {
 //EL PRIMERO ES EL ULTIMO
 uint64_t punteroDirInicio = divisionInicio.rem;
 uint64_t punteroDirFin = punteroOffsetFin;
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(punteros[punteroIndInicio]);
 return liberarBloquesNivel2(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin);
 } else {
 uint64_t i;
 uint8_t error = 0;
 for (i = punteroIndInicio; !error && i <= punteroIndFin; i++) {
 uint64_t punteroDirInicio;
 uint64_t punteroDirFin;
 if (i == punteroIndInicio) {
 punteroDirInicio = divisionInicio.rem;
 punteroDirFin = maxCantBloquesNivelN(3);
 } else if (i == punteroDirFin) {
 punteroDirInicio = 0;
 punteroDirFin = punteroOffsetFin;
 } else {
 punteroDirInicio = 0;
 punteroDirFin = maxCantBloquesNivelN(3);
 }
 uint32_t* bloquePunterosDirectos = (uint32_t*) leerBloqueGlobal(punteros[i]);
 error = liberarBloquesNivel2(numBlockGroup, bloquePunterosDirectos, punteroDirInicio, punteroDirFin);
 }
 return error;
 }
 }

 uint8_t liberarBloquesDeInodo(uint8_t numBlockGroup, inodeStructure_t inodo, uint64_t sizeNuevo) {
 return 0;
 div_t division = div(sizeNuevo, staticSuperBlock.blockSize);
 uint32_t primerBloqueALiberar = division.quot + 1;//la division devuelve el ultimo bloque ocupado, al sumar + 1 tengo el primero a liberar
 if (division.rem == 0 && division.quot != 0) {
 primerBloqueALiberar--;
 }
 uint64_t sizeViejo = inodo.size;
 division = div(sizeViejo, staticSuperBlock.blockSize);
 uint32_t ultimoBloqueALiberar = division.quot;
 if (division.rem == 0 && division.quot != 0) {
 ultimoBloqueALiberar--;
 }
 //SE VE SI SE TIENE QUE AGREGAR ALGUN PUNTERO DIRECTO
 uint64_t puntInicio = primerBloqueALiberar;
 uint64_t puntFin = ultimoBloqueALiberar;
 uint8_t error = 0;
 if (puntInicio < 12 && puntFin < 12) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block, puntInicio, puntFin);
 } else if (puntInicio < 12 && puntFin < 12 + maxCantBloquesNivelN(1)) {
 if (!error) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block, puntInicio, 12);
 if (!error) {
 error = liberarBloquesNivel1(numBlockGroup, inodo.block + 12, 0, puntFin - 12);
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 12, 0, 1);
 }
 }
 }
 } else if (puntInicio < 12 && puntFin < 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 if (!error) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block, puntInicio, 12);
 if (!error) {
 error = liberarBloquesNivel1(numBlockGroup, inodo.block + 12, 0, maxCantBloquesNivelN(1));
 if (!error) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 12, 0, 1);
 if(!error){
 error = liberarBloquesNivel2(numBlockGroup, inodo.block + 13, 0, puntFin - 12 - maxCantBloquesNivelN(1));
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 13, 0, 1);
 }
 }
 }
 }
 }
 //TODO FALTA CONSIDERAR LOS CASOS DE LOS == EJ: }else if(puntInicio < 12 && puntFin >= 12 + maxCantBloquesIndirectosSimples() + maxCantBloquesIndirectosDobles()){
 } else if (puntInicio < 12 && puntFin > 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 if (!error) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block, puntInicio, 12);
 if (!error) {
 error = liberarBloquesNivel1(numBlockGroup, inodo.block + 12, 0, maxCantBloquesNivelN(1));
 if (!error) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 12, 0, 1);
 if(!error){
 error = liberarBloquesNivel2(numBlockGroup, inodo.block + 13, 0, maxCantBloquesNivelN(2));
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 13, 0, 1);
 if (!error) {
 error = agregarBloquesNivel3(numBlockGroup, inodo.block + 14, 0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 14, 0, 1);
 }
 }
 }
 }
 }
 }
 }
 } else if (puntInicio > 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2) && puntFin > 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 if (!error) {
 error = liberarBloquesNivel3(numBlockGroup, inodo.block + 14, puntInicio - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2), puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 }
 } else if (puntInicio > 12 + maxCantBloquesNivelN(1) && puntFin > 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 if (!error) {
 error = liberarBloquesNivel2(numBlockGroup, inodo.block + 13, puntInicio - 12 - maxCantBloquesNivelN(1), maxCantBloquesNivelN(2));
 if (!error) {
 error = liberarBloquesNivel3(numBlockGroup, inodo.block + 14, 0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 14, 0, 1);
 }
 }
 }
 } else if (puntInicio > 12 && puntFin > 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 if (!error) {
 error = agregarBloquesNivel1(numBlockGroup, inodo.block + 12, puntInicio - 12, maxCantBloquesNivelN(1));
 if (!error) {
 error = liberarBloquesNivel2(numBlockGroup, inodo.block + 13, 0, maxCantBloquesNivelN(2));
 if (!error) {
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 13, 0, 1);
 if(!error){
 error = liberarBloquesNivel3(numBlockGroup, inodo.block + 14, 0, puntFin - 12 - maxCantBloquesNivelN(1) - maxCantBloquesNivelN(2));
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 14, 0, 1);
 }
 }
 }
 }
 }
 } else if (puntInicio > 12 && puntFin < 12 + maxCantBloquesNivelN(1) + maxCantBloquesNivelN(2)) {
 if (!error) {
 error = agregarBloquesNivel1(numBlockGroup, inodo.block + 12, puntInicio - 12, maxCantBloquesNivelN(1));
 if (!error) {
 error = liberarBloquesNivel2(numBlockGroup, inodo.block + 13, 0, puntFin - 12 - maxCantBloquesNivelN(1));
 if(!error){
 error = liberarBloquesNivel0(numBlockGroup, inodo.block + 13, 0, 1);
 }
 }
 }
 } else if (puntInicio > 12 && puntFin < 12 + maxCantBloquesNivelN(1)) {
 error = liberarBloquesNivel1(numBlockGroup, inodo.block + 12, puntInicio - 12, puntFin - 12);
 } else if (puntInicio > 12 + maxCantBloquesNivelN(1) && puntFin < 12 + maxCantBloquesNivelN(1)) {
 error = liberarBloquesNivel2(numBlockGroup, inodo.block + 13, puntInicio - 12 - maxCantBloquesNivelN(1), puntFin - 12 - maxCantBloquesNivelN(1));
 }
 return error;
 }*/

int32_t truncar(char* path, off_t size) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Truncar - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("FTRUNCATE - %s - %d\n", path, (uint32_t) size);
//TODO ¿TIENE QUE REVISAR QUE SEA UN ARCHIVO Y NO UN DIRECTORIO?
	inodeStructure_t inodo;
	uint8_t numBlockGroup;
	uint32_t numInodo;
	uint8_t error = obtenerInodoPath(path, &inodo, &numBlockGroup, &numInodo);
	printfCUCA("Encontre el inodo:\n");
//imprimirContenidoInodo(inodo);
	if (!error) {
		uint64_t sizeViejo = inodo.size;
		uint64_t sizeNuevo = size;
		printfCUCA("El size anterior es [%d] y el nuevo es [%d].\n", (uint32_t) sizeViejo, (uint32_t) sizeNuevo);
		div_t division = div(sizeViejo, staticSuperBlock.blockSize);
		uint32_t cantBloquesViejos = division.quot;
		if (division.rem != 0) {
			cantBloquesViejos++;
		}
		division = div(sizeNuevo, staticSuperBlock.blockSize);
		uint32_t cantBloquesNuevos = division.quot;
		if (division.rem != 0) {
			cantBloquesNuevos++;
		}
		printfCUCA("Antes el archivo tenia asociados [%d] bloques, ahora necesita [%d] bloques.\n", cantBloquesViejos, cantBloquesNuevos);
		if (size > inodo.size) {
			printfCUCA("Se necesita agregar tamaño al archivo.\n");
			//tengo que agregar tamanio
			//me fijo si tengo que agregar bloques
			if (cantBloquesViejos != cantBloquesNuevos) {
				printfCUCA("Es necesario agregar bloques.\n");
				//tengo que agregar bloques
				error = agregarOLiberarBloquesAInodoAux(numBlockGroup, &inodo, sizeNuevo, 1); //TODO
				/* posible solucion por si no hay espacio en el grupo de bloques
				 * otra solucion mejor es contar cuantos bloques se van a necesitar
				 * y solo reservar si hay esa cantidad
				 if(error){
				 inodo.size = sizeNuevo;
				 liberarBloquesDeInodo(numBlockGroup, inodo, sizeViejo);
				 }*/
			}
		} else if (size < inodo.size) {
			//tengo que sacar tamanio
			printfCUCA("Se necesita sacarle tamaño al archivo.\n");
			//me fijo si tengo que liberar bloques
			if (cantBloquesViejos != cantBloquesNuevos) {
				//tengo que liberar bloques
				printfCUCA("Es necesario liberar bloques.\n");
				error = agregarOLiberarBloquesAInodoAux(numBlockGroup, &inodo, sizeNuevo, 0); //TODO
			}
		}
		if (!error) {
			//actualizo la estructura del inodo y la escribo
			inodo.size = size;
			division = div(inodo.size, staticSuperBlock.blockSize);
			uint32_t cantBlocks512 = division.quot * (staticSuperBlock.blockSize / 512);
			if (division.rem != 0) {
				cantBlocks512 += staticSuperBlock.blockSize / 512;
			}
			inodo.blocks = cantBlocks512;
			escribirInodo(inodo, numInodo);
			//imprimirContenidoInodoExtendido(inodo); //TODO
			//desbloqueo el inodo
			/*TODO*/dejoDeTrabajarEnInodo(numInodo);
			return 0; //EN CASO DE EXITO DEVUELVE 0
		} else {
			//NO HAY SUFICIENTE ESPACIO EN EL DISCO
			//desbloqueo el inodo
			/*TODO*/dejoDeTrabajarEnInodo(numInodo);
			return -ENOSPC; //NO HAY SUFICIENTE ESPACIO
		}
	} else {
		//no es necesario desbloquear el inodo, si no existe no queda bloqueado
		return -ENOENT;
	}
}

int32_t truncarInodo(uint32_t numInodo, uint8_t numBlockGroup, inodeStructure_t* inodo, off_t size) {
	uint8_t error = 0;
	uint64_t sizeViejo = (*inodo).size;
	uint64_t sizeNuevo = size;
	printfCUCA("El size anterior es [%d] y el nuevo es [%d].\n", (uint32_t) sizeViejo, (uint32_t) sizeNuevo);
	div_t division = div(sizeViejo, staticSuperBlock.blockSize);
	uint32_t cantBloquesViejos = division.quot;
	if (division.rem != 0) {
		cantBloquesViejos++;
	}
	division = div(sizeNuevo, staticSuperBlock.blockSize);
	uint32_t cantBloquesNuevos = division.quot;
	if (division.rem != 0) {
		cantBloquesNuevos++;
	}
	printfCUCA("Antes el archivo tenia asociados [%d] bloques, ahora necesita [%d] bloques.\n", cantBloquesViejos, cantBloquesNuevos);
	if (size > (*inodo).size) {
		printfCUCA("Se necesita agregar tamaño al archivo.\n");
		//tengo que agregar tamanio
		//me fijo si tengo que agregar bloques
		if (cantBloquesViejos != cantBloquesNuevos) {
			printfCUCA("Es necesario agregar bloques.\n");
			//tengo que agregar bloques
			error = agregarOLiberarBloquesAInodoAux(numBlockGroup, inodo, sizeNuevo, 1); //TODO
			/* posible solucion por si no hay espacio en el grupo de bloques
			 * otra solucion mejor es contar cuantos bloques se van a necesitar
			 * y solo reservar si hay esa cantidad
			 if(error){
			 inodo.size = sizeNuevo;
			 liberarBloquesDeInodo(numBlockGroup, inodo, sizeViejo);
			 }*/
		} else {
			printfCUCA("No es necesario agregar bloques.\n");
		}
	} else if (size < (*inodo).size) {
		//tengo que sacar tamanio
		printfCUCA("Se necesita sacarle tamaño al archivo.\n");
		//me fijo si tengo que liberar bloques
		if (cantBloquesViejos != cantBloquesNuevos) {
			//tengo que liberar bloques
			printfCUCA("Es necesario liberar bloques.\n");
			error = agregarOLiberarBloquesAInodoAux(numBlockGroup, inodo, sizeNuevo, 0); //TODO
		}
	}
	if (!error) {
		//actualizo la estructura del inodo y la escribo
		(*inodo).size = size;
		division = div((*inodo).size, staticSuperBlock.blockSize);
		uint32_t cantBlocks512 = division.quot * (staticSuperBlock.blockSize / 512);
		if (division.rem != 0) {
			cantBlocks512 += staticSuperBlock.blockSize / 512;
		}
		(*inodo).blocks = cantBlocks512;
		escribirInodo((*inodo), numInodo);
		//imprimirContenidoInodoExtendido(inodo); //TODO
		//desbloqueo el inodo
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
		return 0; //EN CASO DE EXITO DEVUELVE 0
	} else {
		//NO HAY SUFICIENTE ESPACIO EN EL DISCO
		//desbloqueo el inodo
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
		return -ENOSPC; //NO HAY SUFICIENTE ESPACIO
	}
}

//----------------------------------------------------------------------------------------------------
//OBTENER ATRIBUTOS
//----------------------------------------------------------------------------------------------------

int32_t obtenerAtributos(char* path, attrDirArch_t *attr) {
	//loguearDatosTemplate("DEBUG", time(NULL), "RFS", (uint32_t) getpid(), (uint32_t) pthread_self(), NIVEL_LOG_OBLIGATORIO, "Obtener atributos - Path [%s]", path);
	printfCUCA("===============================================================================\n");
	printfCUCA("GETATTR - %s\n", path);
	inodeStructure_t inodo;
	uint8_t numBlockGroup;
	uint32_t numInodo;
	uint8_t error = obtenerInodoPath(path, &inodo, &numBlockGroup, &numInodo);
	printf("<obtenerAtributos> numInodo: %d\n", numInodo);
	if (!error) {
		//desbloqueo el inodo, si no existe no esta bloqueado
		/*TODO*/dejoDeTrabajarEnInodo(numInodo);
		attr->modo = inodo.mode;
		attr->size = (off_t) inodo.size;
		return 0;
	} else {
		return -ENOENT;
	}
}

char* leerGrupoDeBloques(uint64_t numGroup, uint32_t blockPerGroup, uint32_t blockSize, FILE* particion) {
	char* contenido = malloc(blockPerGroup * blockSize);
	fseek(particion, 1024 + (numGroup * blockPerGroup * blockSize), SEEK_SET);
	memcpy(&contenido, particion, blockPerGroup * blockSize);
	return contenido;
}

uint16_t esGrupoConSuperBloque(uint64_t numeroDeGrupo) {
	if ((numeroDeGrupo == 0) || (numeroDeGrupo == 1) || (esPotencia(numeroDeGrupo, 3)) || esPotencia(numeroDeGrupo, 5) || esPotencia(numeroDeGrupo, 7))
		return 1;
	else
		return 0;
}

void finalizarExtended2(void) {
//TODO LIBERAR LOS SEMAFOROS
	if (staticGroupDescriptorTable != NULL) {
		free(staticGroupDescriptorTable);
		staticGroupDescriptorTable = NULL;
	}
}
